Reputation: 325
I am new to react and I am trying to count each character from textarea and display the character count. I have done the total character count but How do I count each character and display the number of characters? My code is follows :
import React, { useState } from "react";
function Home() {
const [characterCount, setCharacterCount] = useState(0);
const myFunction = (e) => {
e.preventDefault();
console.log("clicked");
};
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={(e) => setCharacterCount(e.target.value.length)}
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>Total number of character :{characterCount}</p>
</form>
</div>
);
}
export default Home;
output: user input
abbbsewrrrrree
Total number of characters: 14
Expected: Example: if user input:
abbbsewrrrrree
a=1
b=3
s=1
e=3
w=1
r=5
Upvotes: 0
Views: 2487
Reputation: 190
Check that solution, got the character count function here.
function Char_Count(str1) {
let chars = {};
str1.replace(/\S/g, function (l) {
chars[l] = isNaN(chars[l]) ? 1 : chars[l] + 1;
});
return chars;
}
function Home() {
const [characterCount, setCharacterCount] = useState({});
const onTextAreaChange = (e) => {
setCharacterCount(Char_Count(e.target.value));
};
const myFunction = (e) => {
e.preventDefault();
console.log("clicked");
};
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={onTextAreaChange}
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>All character counts:</p>
{Object.keys(characterCount).map((item, i) => (
<p key={i}>
{item}: {characterCount[item]}
</p>
))}
</form>
</div>
);
}
If we want to sort the characterCount
object based on the most repeated character, we can update the onTextAreaChange
to this:
const onTextAreaChange = (e) => {
const countObj = Char_Count(e.target.value);
const sortableCountObj = Object.entries(countObj)
.sort(([, a], [, b]) => b - a)
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {});
setCharacterCount(sortableCountObj);
};
Upvotes: 0
Reputation: 618
I think you should make the input(textarea) controlled, as you would like to process the value (to count each character). React Controlled Components
function Home() {
const [text, setText] = useState('');
const myFunction = (e) => {
e.preventDefault();
console.log('clicked');
};
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={(e) => setText(e.target.value)}
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>Total number of character :{text.length}</p>
</form>
</div>
);
}
And for counting each character you could use useMemo
and watch state text
changes, like this:
function Home() {
const [text, setText] = useState('');
const myFunction = (e) => {
e.preventDefault();
console.log('clicked');
};
const eachCharResult = useMemo(() => {
let result = {};
for (let i = 0; i < text.length; i++) {
if (result[text[i]]) result[text[i]]++;
else result[text[i]] = 1;
}
return result;
}, [text]);
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={(e) => setText(e.target.value)}
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>Total number of character :{text.length}</p>
</form>
{Object.keys(eachCharResult).map((el, i) => (
<p key={i}>{`${el}: ${eachCharResult[el]}`}</p>
))}
</div>
);
}
Ignoring space, you can solve like this:
const removeSpace = (text) => text.replace(/\s/g, '');
function Home() {
const [text, setText] = useState('');
const myFunction = (e) => {
e.preventDefault();
console.log('clicked');
};
const eachCharResult = useMemo(() => {
let result = {};
let textWithoutSpace = removeSpace(text);
for (let i = 0; i < textWithoutSpace.length; i++) {
if (result[textWithoutSpace[i]]) result[textWithoutSpace[i]]++;
else result[textWithoutSpace[i]] = 1;
}
return result;
}, [text]);
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={(e) => setText(e.target.value)}
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>Total number of character :{removeSpace(text).length}</p>
</form>
{Object.keys(eachCharResult).map((el, i) => (
<p key={i}>{`${el}: ${eachCharResult[el]}`}</p>
))}
</div>
);
}
Upvotes: 2
Reputation: 1180
Maybe something like this (I didn't run it)
import React, { useState } from "react";
// new
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const counts = {}
alphabet.split('').forEach(letter => counts[letter] = 0)
function Home() {
const [characterCount, setCharacterCount] = useState(0);
// new
const [letterCount, setLetterCount] = useState(counts)
// new
const onTextChange = e => {
setCharacterCount(e.target.value.length)
// update count for letter
const l = e.target.value[e.target.value.length -1]
letterCount[l] += 1
setLetterCount(letterCount)
}
const myFunction = (e) => {
e.preventDefault();
console.log("clicked");
};
return (
<div>
<form onSubmit={myFunction}>
<h3>Please enter text</h3>
<textarea
onChange={(e) => onTextChange(e)} // <-- new
placeholder="start typing"
></textarea>
<div>
<button type="submit">submit</button>
</div>
<p>Total number of character :{characterCount}</p>
{
// new
Object.keys(letterCount).map(li => {
return <p key={`key-${li}`>{li}: {letterCount[li]}</p>
})
}
</form>
</div>
);
}
export default Home;
Upvotes: 0