2

I'm trying to update the state of an array with React Hooks, using an input received from a child component.

This is the code for the array I'm trying to update (in my App.js file):

 const [results, setResults] = useState([]);

  const submitHandler = newResult => {
    const newArray = [...results, newResult];
    setResults(newArray);
    console.log(newArray);
    console.log(results);
  }

The newArray is updated and logged properly, with all the items that are submitted through the child component. But the state of results is never updated, and it always logs an empty array. It should be noted that other useState hooks in my app are working properly, only the one I'm using for this array isn't working. Does anyone know what could be wrong and how can it be fixed?

If it helps, this is the code that submits the items from the child component (Shorten.js) - these hooks are working perfectly fine:

    const [urlInput, setUrlInput] = useState("");
    const [error, setError] = useState(false);

    const changeHandler = event => {
        setUrlInput(event.target.value);
    }

    const submitHandler = event => {
        event.preventDefault();

        if (urlInput === "") {
            setError(true);
        }
        else {
            setError(false);

            axios.post("https://rel.ink/api/links/", {
                url: urlInput
            })
                .then(response => {
                    const newResult = {
                        original: urlInput,
                        shortened: "https://rel.ink/" + response.data.hashid
                    }

                    props.submit(newResult);
                })
                
            setUrlInput("");
        }
    }
Yinon Hever
  • 39
  • 1
  • 1
  • 5
  • Duplicate of [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Guy Incognito Jul 03 '20 at 12:52

1 Answers1

6

In your example, you cannot guarantee the results state has been updated at the point of your console.log(results). This is because the React state update as asynchronous and applied in batches under the hood.

If you had your console.log call under const [result, setResults] = useState([]) then it will get called on every render pass, and therefore you should see the updated value logged out once the setState function has applied your new state.

For example:

const [results, setResults] = useState([]);

console.log(results);

const submitHandler = newResult => {
  const newArray = [...results, newResult];
  setResults(newArray);
  console.log(newArray);
}

should log your new state on the next render pass.

You could also put your console.log in a useEffect which will let you know for sure that React knows your results have changed.

const [results, setResults] = useState([]);

useEffect(() => {
  console.log(results);
}, [results]);

const submitHandler = newResult => {
  const newArray = [...results, newResult];
  setResults(newArray);
  console.log(newArray);
}

This means your console.log(results) will only be called when results changed, rather then on every render.

mbrookson
  • 435
  • 4
  • 15