Search code examples
reactjssetstateuse-effect

value of state is always default. React js 16.12.0


I have two useEffect-s. One is used to fetch data from api and save it in the state and second is called only once and it starts listening to websocket event. In the websocket event handler I log the fetched data but it always has the default value. Even though fetching data completes successfully and the list is drawn on UI, the value of list is always empty - [].

const [list, setList] = useState([]);

useEffect(() => {
   axios.get("https://sample.api.com/get/list")
       .then(res => {
           setList(res.data);
       });
}, [window.location.pathname.split('/')[2]]);

useEffect(() => {
   webSocket.on('messageRecieved', (message) => {
        console.log(list);
    }); 
}, []);

Solution

  • Your second effect is referencing the initial list value (an empty array) due to closure. This is why useEffect should reference all of its dependencies in its second argument.

    But in this case, where you don't want to subscribe to the webSocket event each time the list is updated, you could use React's refs on the list.

    const listValue = useRef([]);
    const [list, setList] = useState(listValue.current);
    

    When setting the value:

    res => {
        listValue.current = res.data
        setList(listValue.current);
    }
    

    And when retrieving the list in a one time fired useEffect:

    useEffect(() => {
        webSocket.on('messageRecieved', (message) => {
           console.log(listValue.current);
        }); 
    }, []);