Search code examples
javascriptreactjsreact-hooksuse-state

The best way of the using useState hook in Function Component?


I want to show a div related to an object property that comes true or false. And I used a way but I'm not sure it's the best way or is it open the performance problems.

I'm checking that property in the loop that in return section for avoid extra array operation. But I think it will cause extra render.

The other option is checking that property in outside from return section. But this will be cause an extra array operation.

Which is the best way for me? I showed 2 different implementation below.

Option 1:

const RadioButtonList: FunctionComponent<RadioButtonListProps> = ({ items, changeFilter }) => {
  const [showClearIcon, setShowClearIcon] = React.useState(false);
  
  return (
    <div className="radio-button-list">
      {showClearIcon && <div className="clear-icon">clear</div>}
      <ul>
        {items.map(item => {
          /* this is the area what I'm checking the property */
          if (item.selected) {
            setShowClearIcon(true);
          }
          return (
            <li key={item.id}>
              <label htmlFor={item.text} className="radio">
                <span className="input">
                  <input type="radio" onClick={changeFilter} readOnly />
                </span>
              </label>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

Option 2:

const RadioButtonList: FunctionComponent<RadioButtonListProps> = ({ items, changeFilter }) => {
  const [showClearIcon, setShowClearIcon] = React.useState(false);


  /* set in useEffect hook */
  useEffect(() => {
    if(items.some(item => item.selected)) {
      setShowClearIcon(true);
    }
  }, [items]);
  
  return (
    <div className="radio-button-list">
      {showClearIcon && <div className="clear-icon">clear</div>}
      <ul>
        {items.map(item => {
          return (
            <li key={item.id}>
              <label htmlFor={item.text} className="radio">
                <span className="input">
                  <input type="radio" onClick={changeFilter} readOnly />
                </span>
              </label>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

Solution

  • It looks like showClearIcon doesn't need to be a state atom at all, but just a memoized value dependent on items.

    const showClearIcon = React.useMemo(
      () => items.some(item => item.selected), 
      [items],
    );