0

I might be missing something (almost certain of it), but when I "set" a state array, if the array only has one item, the state, is empty. If I "set" an array with more than one item, the state array has one less item.

Probably best shown with a sample. (watch console).

codesandbox

import React, {useState} from "react";
import "./styles.css";
import Select from "react-select";

export default function App() {
  const [items, setItems] = useState([]);

  const options = [
    {value: 1, label: "Item 1"},
    {value: 2, label: "Item 2"},
    {value: 3, label: "Item 3"},
    ]

  function hanldeItemChange(selectedItems) {
    //This prints all object in console
    console.log(`selectedItems = ${selectedItems}`);
    var mappedItems = selectedItems.map(item => item.value);
    //This prints just the values as an array (correctly)
    console.log(`mappedItems = ${mappedItems}`);
    setItems(mappedItems);
    //This print the values from my state array, but it does not match the "MappedItems"
    console.log(`items = ${items}`);
  }

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Select
          className="basic-multi-select"
          classNamePrefix="select"
          onChange={hanldeItemChange}
          isMulti
          name="Items"
          options={options}
        />

    </div>
  );
}
Ahmed Sbai
  • 10,695
  • 9
  • 19
  • 38
Angryjames
  • 77
  • 9
  • 1
    setState is async. You cannot see updated data (like console.log) after setState. use useeffect with dependency [items] re-render every items state change – Nijat Aliyev Mar 16 '23 at 15:18
  • Does the state not actually reflect until the "setting" function/caller is complete? – Angryjames Mar 16 '23 at 15:18
  • 1
    https://dev.to/shareef/react-usestate-hook-is-asynchronous-1hia – Nijat Aliyev Mar 16 '23 at 15:19
  • 1
    Just to make it cristal clear to anyone seeing this question: the problem is that setItem is run AFTER the onChange function is complete due to it's asynchronous nature. – Nelson Teixeira Mar 16 '23 at 15:30
  • Does this answer your question? [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) – RubenSmn Mar 16 '23 at 16:40

1 Answers1

0

I was misunderstanding how useState was working. As Nijat suggested, using useEffect will work for what I need.

import React, {useState, useEffect} from "react";
import "./styles.css";
import Select from "react-select";

export default function App() {
  const [items, setItems] = useState([]);
  useEffect(() => {
    console.log(items)
  }, [items])

  const options = [
    {value: 1, label: "Item 1"},
    {value: 2, label: "Item 2"},
    {value: 3, label: "Item 3"},
    ]

  function hanldeItemChange(selectedItems) {
    console.log(`selectedItems = ${selectedItems}`);
    var mappedItems = selectedItems.map(item => item.value);
    console.log(`mappedItems = ${mappedItems}`);
    setItems(mappedItems);
    console.log(`items = ${items}`);
  }

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Select
          className="basic-multi-select"
          classNamePrefix="select"
          onChange={hanldeItemChange}
          isMulti
          name="Items"
          options={options}
        />

    </div>
  );
}
Angryjames
  • 77
  • 9