Home > Blockchain >  React state doesn't update immediately with useState
React state doesn't update immediately with useState

Time:05-24

Apologies if you feel like this is a repeated question, but I couldn't find the solution for my problem in any of similar questions and couldn't understand why this problem was occurring.

I have a component called Selector.tsx which basically has an input field and a bunch of buttons that when clicked are supposed to create a card with the data from that input field.

selector.tsx:


const profileList: Profile[] = [
  {
    name: 'Website',
    value: 'website',
  },
  {
    name: 'Documentation',
    value: 'documentation',
  },
  {
    name: 'Telegram',
    value: 'telegram',
  },
  {
    name: 'Twitter',
    value: 'twitter',
  },
  {
    name: 'Github',
    value: 'github',
  },
  {
    name: 'Facebook',
    value: 'facebook',
  },
  {
    name: 'Blog',
    value: 'blog',
  },
  {
    name: 'Discord',
    value: 'discord',
  },
  {
    name: 'LinkedIn',
    value: 'linkedin',
  },
  {
    name: 'Slack',
    value: 'slack',
  },
];

export const Selector: FC<SelectorProps> = ({ wrapperClass }) => {
  const [inputVal, setInputVal] = useState('https://google.com');
  const [saved, setSaved] = useState<Saved[]>([]);

  const handleAdd = (val: string) => {
    if (!inputVal) return;
    const _saved = saved;
    _saved.push({ type: val, text: inputVal });
    setSaved(_saved);
  };

  const handleClearSaved = () => {
    setSaved([]);
  };

  const DisplayCard: FC<DisplayCardProps> = ({ text, type }) => (
    <div className="w-full text-left text-text-gray bg-red-100 px-4 py-1 border rounded-lg">
      <span className="text-gray-600 text-xs">{type}:</span>
      <span className="text-base text-black text-sm ml-4">{text}</span>
    </div>
  );

  return (
    <div className="mt-4 py-4 flex flex-col lg:flex-row-reverse gap-4 items-center">
      <div className="mt-8 space-y-2 overflow-y-auto border border-blue-500 p-4 rounded">
        {saved.length ? (
          saved.map(({ type, text }, i) => (
            <DisplayCard key={i} text={text} type={type} />
          ))
        ) : (
          <i>Nothing to show</i>
        )}
      </div>
      <div className="border rounded p-4">
        <div className="flex items-center gap-2">
          <input
            className="flex-grow pl-2 text-sm leading-6 border border-transparent bg-blue-100 rounded outline-none focus:border-prim-border"
            value={inputVal}
            onChange={(e) => setInputVal(e.target.value)}
          />
          <div className="mt-2 flex flex-col space-y-2">
            {profileList.map(({ name, value }, i) => (
              <button
                className="border border-red-400 text-sm bg-black bg-opacity-0 hover:bg-opacity-10 transform scale-100 active:scale-90 disabled:cursor-not-allowed"
                onClick={() => handleAdd(value)}
                disabled={!inputVal}
              >
                {name}
              </button>
            ))}
          </div>
        </div>
        <button
          className="mt-2 border border-red-500 transform scale-100 active:scale-90 px-2"
          onClick={handleClearSaved}
        >
          Clear Fields
        </button>
      </div>
    </div>
  );
};

Whenever we click any of the profile buttons (and the input field is not empty), the handleSave button is called & saved array state is supposed to get updated(object is pushed into the array) & based on that, DisplayCards are rendered.

The problem: The saved state doesn't get updated after any of the profile buttons are clicked. When we make changes in the input field(which updates the inputVal state), only then the saved state gets updated

Also weirdly enough, the handleClearSaved function works properly when the clear button is clicked. It is able to empty the saved array. But for some reason, pushing into the saved array doesn't seem to update the state.

Problem repoduced in Stackblitz: https://stackblitz.com/edit/well-well-well?file=components/Selector.tsx

I can't wrap my head around, why this behavior is occurring in react. I've never encountered such issues before. If any one can help or provide any hints on this, it would be really helpful.

  • Related