0

I have the next situation in my react application:

export default function App() {
  const arr  = []
  useEffect(() => {
    arr.push('test')
  },[])
  console.log(arr)
  return (
    <div className="App">
        {
          arr.map((i) => <span>{i}</span>)
        }
    </div>
  );
}

Above i try to push a new item in the array. So in the console.log(arr) i expect to have ['test']. Why it does not happen?
demo: https://codesandbox.io/s/reverent-mayer-pxswq?file=/src/App.js:59-294

5 Answers 5

2

useEffect runs in the next frame, so it won't be populated until later.

You should try this:

  const arr  = []
  useEffect(() => {
    arr.push('test')
    console.log(arr)
  },[])

You also don't want to be setting state like that, use useState.

const [arr, setArr] = useState([])

useEffect(() => {
  setArr(a => [...a, 'test'])
}, [arr])
Sign up to request clarification or add additional context in comments.

2 Comments

how i can get the arr values outside useEffect?
through useState.
2

You should use the state hook for your arr.

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [arr, setArr] = useState([]);
  useEffect(() => {
    setArr([...arr, "test"]);
  }, []);
  console.log(arr);
  return (
    <div className="App">
      {arr.map((i) => (
        <span>{i}</span>
      ))}
    </div>
  );
}

Comments

0

The code you shared is working but the console.log is not at the good place. Your console.log is login before the useEffect();

export default function App() {
  const arr  = []
  useEffect(() => {
    arr.push('test');
    console.log('After UseEffect', arr);
  },[])
  console.log('Before UseEffect',arr)
  return (
    <div className="App">
        {
          arr.map((i) => <span>{i}</span>)
        }
    </div>
  );
}

Comments

0

In your case, useEffect run after console.log so arr still empty when log,

Agree with @Stoobish, but:

  1. Tracking arr change should use useDebugValue or log inside useEffect
  2. If you want to prevent duplicate render when state change, use useEffectLayout instead of useEffect.
    import { useEffect, useLayoutEffect, useState } from "react";
    import "./styles.css";
    
    export default function App() {
      const [arr, setArr] = useState([]);
      useLayoutEffect(() => {
        setArr([...arr, "test"]);
      }, []);
      useEffect(() => {
        console.log(arr);
      }, [arr])
      return (
        <div className="App">
          {arr.map((i) => (
            <span key={i}>{i}</span>
          ))}
        </div>
      );
    }

Comments

0

You should consider three point below:

  1. You should use useState hook.

So Use

const [arr, setArr] = useState([]);

Not

const arr  = []

When you use React you must consider useState because when you update any variable using useState Hook then React will update the state and can be able to rerender your component. Otherwise, your component will not be updated.

  1. You should not push directly into the array arr.

So Use

setArr(item => [...item, newItem])

Not

arr.push('test')

As I explain it above, if you dont use setArr then React will not update your component.

  1. You should use key when you use multiple html element using map function.

So Use

{arr.map((a, i) => (
            <span key={i}>{a}</span>
          ))}

Not

arr.map((i) => <span>{i}</span>)

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

Here is the complete example:

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [arr, setArr] = useState([]);

  useEffect(() => {
    let newItem = 'test';
    setArr(item => [...item, newItem]); // Here we are using `spread operator` to use previous items from `arr`
    console.log(arr);
  }, []);

  
  return (
    <div className="App">
      {arr.map((a, i) => (
        <span key={i}>{a}</span>
      ))}
    </div>
  );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.