简体   繁体   中英

Data from redux store returns undefined when page is refreshed

When I access the FeedbackDetails page, initially there's no issue because the state loaded from the previous page (Home page) is still available. But when I tried to refresh the page, it returns an error: TypeError: Cannot destructure property 'title' of 'feedback' as it is undefined.

Here are the codes:-

Home Page

import React, { useEffect } from "react";
import Header from "../components/Home/Header/Header";
import Main from "../components/Home/Main/Main";
import { useDispatch } from "react-redux";
import { fetchData, updateData } from "../actions/dataActions";

const Home = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    const data = JSON.parse(localStorage.getItem("data"));

    if (!data) {
      dispatch(fetchData());
    }

    dispatch(updateData(data));
  }, [dispatch]);

  return (
    <StyledContainer>
      <Header />
      <Main />
    </StyledContainer>
  );
};

........

FeedbackDetails Page

mport React, { useEffect } from "react";
import styled from "styled-components";
import Feedback from "../components/Home/Main/Feedback";
import Comments from "../components/FeedbackDetails/Comments";
import AddComment from "../components/FeedbackDetails/AddComment";
import { useParams, useHistory } from "react-router-dom";
import { totalComments } from "../utils/utilityFunctions";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { updateData } from "../actions/dataActions";

const FeedbackDetails = () => {
  const dispatch = useDispatch();
  const history = useHistory();
  const { id } = useParams();
  const feedbackId = id;

  useEffect(() => {
    const storagedata = JSON.parse(localStorage.getItem("data"));
    dispatch(updateData(storagedata));

    window.scrollTo({
      top: 0,
    });
  }, [dispatch]);

  const data = useSelector((state) => state.data);
  const productRequests = data.productRequests;
  const feedback = productRequests.filter((item) => item.id === Number(id))[0];
  const { title, category, upvotes, description, comments } = feedback;

.............
}

Data Actions

export const updateData = (data) => async (dispatch) => {
  dispatch({
    type: "UPDATE_DATA",
    payload: {
      currentUser: data.currentUser,
      productRequests: data.productRequests,
    },
  });
};

Data Reducer

const initialState = {
  currentUser: {},
  productRequests: [],
  category: "",
};

const dataReducer = (state = initialState, action) => {
  switch (action.type) {
    case "FETCH_DATA":
      return {
        ...state,
        currentUser: action.payload.currentUser,
        productRequests: action.payload.productRequests,
      };

    case "FILTER_DATA":
      return {
        ...state,
        currentUser: action.payload.currentUser,
        productRequests: action.payload.productRequests,
        category: action.payload.category,
      };

    case "UPDATE_DATA":
      return {
        ...state,
        currentUser: action.payload.currentUser,
        productRequests: action.payload.productRequests,
      };

    default:
      return { ...state };
  }
};
..............

Reducer Index

import { combineReducers } from "redux";
import dataReducer from "./dataReducer";

const rootReducer = combineReducers({
  data: dataReducer,
});

export default rootReducer;

I tried digging deeper into the problem and found out that data (from the redux store) in the FeedbackDetails page is undefined when refreshed. I thought my useEffect code should resolve this when I dispatch updateData(storagedata) , but this doesn't seem to be the case. It seems that the dispatch is not updating quicker than the page loads.

How can I resolve this problem?

As pointed by hisam , I managed to find a workable solution based on the suggested thread .

For anybody who's interested, what I did was, I changed my initialState in my dataReducer as follows:-

const storagedata = JSON.parse(localStorage.getItem("data"));

const initialState = {
  currentUser: storagedata.currentUser || {},
  productRequests: storagedata.productRequests || [],
  category: "",
};

It keeps the redux store hydrated, and prevent the "undefined" issue that persists. I also tried using the redux-persist library, but somehow I couldn't get it to work as intended. Hence, I opted for the above solution.

You can get used of react persist a library that will store the redux state in your local storage and can be availed even after refresh. In this, you can even whitelist the elements that are to stored in the localstorage and can leave others.

https://github.com/NaveenkumarMD/create-mern-app/tree/master/template/reactpersist

The above is the link for the implementation of react persist.You can clone this and can understand how to work on it.

https://www.npmjs.com/package/redux-persist

I used to have the same problem When I was trying to render data from an Api, when I refreshit the Api shows me that error, the solution that I found was to add && as a render condition. This ask to the Api if we have this new information then render if not just keep it like that enter image description here

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