简体   繁体   中英

useState variable returning empty array while i set it to an array of objects

Hello I have a component as follows I'm using usestate hook to initialize the myFeeds variabele to the feeds array and I'm running an effect to add any data from server (socket.io) However when I'm console logging the result myFeeds is giving me an empty array what could be the possible reasons?

const Dashboard = ({feeds}) => {

useEffect(() => {
getFeeds(); // this fetches feeds array
}, []);

const [myFeeds, setMyFeeds] = useState(feeds);

// useEffect hook to get real time messages and add it to feed

useEffect(() => {
let mount = true;

io.on('created' (data) => {
  if(mount) {
  data && setMyFeeds([...feeds, data]);
  }
 }
}, [])


console.log(feeds); // gives array of objects
console.log(myFeeds); // giving empty array

return(
<FeedBody body={myFeeds} />
);

}

// mapstatetoprops here

getFeeds is an action creator which is as follows

export const getFeeds = () =>  async dispatch => {

const res = await axios.get('/feeds');
// dispatch type get feeds here set payload to result of above operation
}

I don't know if it's the problem, but the way you're taking the feeds prop and turning it into the myFeeds state is definitely problematic, in a couple of ways:

  1. Your component won't see updates to its feeds prop if the parent calls it again with a new value. Remember that the value you pass into useState is only used when your component is first created , it's not used on subsequent calls to your component function (the current state of your component is used instead).

  2. The feeds you're using in your io.on callback may be stale, because you have an empty dependencies array in your useEffect call; by the time io.on calls your callback, your component function may have been called with an updated feeds (which you would see in your console.log ) but the one used with setMyData will be stale (the original one closed over by the callback when it was created during the first call to your component function).

Here's what I'm referring to in #2:

useEffect(() => {
    let mount = true;

    io.on('created' (data) => {
        if(mount) {
            data && setMyFeeds([...feeds, data]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^−−−−−−−−−−−− may be stale!
        }
    }
}, [])

You probably want to move the io.on call out of this component and put it in the parent, and have the parent re-render this component when feeds changes.

If you decide not to do that, the minimum change you need to make is to not use that stale feeds parameter value. Instead, use the callback form:

useEffect(() => {
    let mount = true;

    io.on('created' (data) => {
        if(mount) {
            data && setMyFeeds(myFeeds => [...myFeeds, data]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^−−−−−−−^^^^^^^−−−−−−−−−−−− up to date
        }
    }
}, [])

But again, your component will miss an updates to feeds that the arent sends it.

This note in the documentation about copying props to state when using hooks may be a useful read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM