简体   繁体   中英

How to count each character from the textarea using react and display total count?

I am new to react and I am trying to count each character from textarea and display the character count. I have done total character count but How do I count each character and display number of character ? 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 character : 14

Expected: Example: if user input:

abbbsewrrrrree

a=1
b=3
s=1
e=3
w=1
r=5

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> ); }

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;

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);
  };

编辑 react-count-each-character

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM