HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptTip

Create a textarea React component with word or character limit

Submitted by: @import:30-seconds-of-code··
0
Viewed 0 times
limittextareawithreactcharactercomponentwordcreate

Problem

The <textarea> element is a multi-line text input control that allows users to enter text. React allows you to enhance its functionality by creating custom components that can have additional features, such as a word or character limit.
The simplest version of a <textarea> component is an uncontrolled one. It uses the defaultValue prop passed down from the parent as the initial value of the input field. The onChange event is used to fire the onValueChange callback and send the new value to the parent.
A controlled <textarea> component instead uses the value prop to manage the input field's value. The onChange event is used to update the value prop with the new value. Taking this a step further, we can use the useState() hook to create a state variable, content. For this variant, it won't do much more than mirror the value prop.
Expanding upon the controlled <textarea> component, we can add a character limit to it. The useState() hook is used to create the content state variable, which is set to the value prop trimmed down to limit characters. A method, setFormattedContent, is created to trim the content down to limit characters and memoize it using the useCallback() hook. The onChange event of the <textarea> is bound to call setFormattedContent with the value of the fired event.
Similarly, we can create a <textarea> component with a word limit. The implementation is much the same as before, except that we use String.prototype.split() to turn the input into an array of words. The setFormattedContent method is then used to trim the input down to limit words.

Solution

const TextArea = ({
  cols = 20,
  rows = 2,
  defaultValue,
  onValueChange,
  ...rest
}) => {
  return (
    <textarea
      cols={cols}
      rows={rows}
      defaultValue={defaultValue}
      onChange={({ target: { value } }) => onValueChange(value)}
      {...rest}
    />
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <TextArea
    placeholder="Insert some text here..."
    onValueChange={val => console.log(val)}
  />
);


A controlled <textarea> component instead uses the value prop to manage the input field's value. The onChange event is used to update the value prop with the new value. Taking this a step further, we can use the useState() hook to create a state variable, content. For this variant, it won't do much more than mirror the value prop.
Expanding upon the controlled <textarea> component, we can add a character limit to it. The useState() hook is used to create the content state variable, which is set to the value prop trimmed down to limit characters. A method, setFormattedContent, is created to trim the content down to limit characters and memoize it using the useCallback() hook. The onChange event of the <textarea> is bound to call setFormattedContent with the value of the fired event.
Similarly, we can create a <textarea> component with a word limit. The implementation is much the same as before, except that we use String.prototype.split() to turn the input into an array of words. The setFormattedContent method is then used to trim the input down to limit words.

Code Snippets

const TextArea = ({
  cols = 20,
  rows = 2,
  defaultValue,
  onValueChange,
  ...rest
}) => {
  return (
    <textarea
      cols={cols}
      rows={rows}
      defaultValue={defaultValue}
      onChange={({ target: { value } }) => onValueChange(value)}
      {...rest}
    />
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <TextArea
    placeholder="Insert some text here..."
    onValueChange={val => console.log(val)}
  />
);
const TextArea = ({ cols = 20, rows = 2, value, onChange, ...rest }) => {
  const [content, setContent] = React.useState(value);

  return (
    <textarea
      cols={cols}
      rows={rows}
      value={content}
      onChange={event => {
        setContent(event.target.value);
        onChange(event.target.value);
      }}
      {...rest}
    />
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <TextArea
    placeholder="Insert some text here..."
    value="Hello, world!"
    onChange={val => console.log(val)}
  />
);
const LimitedTextarea = ({ rows, cols, value, limit }) => {
  const [content, setContent] = React.useState(value.slice(0, limit));

  const setFormattedContent = React.useCallback(
    text => {
      setContent(text.slice(0, limit));
    },
    [limit, setContent]
  );

  return (
    <>
      <textarea
        rows={rows}
        cols={cols}
        onChange={event => setFormattedContent(event.target.value)}
        value={content}
      />
      <p>
        {content.length}/{limit}
      </p>
    </>
  );
};

ReactDOM.createRoot(document.getElementById('root')).render(
  <LimitedTextarea limit={32} value="Hello!" />
);

Context

From 30-seconds-of-code: limited-textarea

Revisions (0)

No revisions yet.