【问题标题】:React redux shows previous state old data before fetching new dataReact redux 在获取新数据之前显示先前状态的旧数据
【发布时间】:2021-01-15 12:35:09
【问题描述】:

我使用 React-Redux 和带有钩子的功能组件。 每当我发送从服务器获取数据的请求时,我将全局状态的 isLoading 字段设置为 true,然后在请求完成后返回 false。 在渲染组件中,如果 isLoading 设置为 true,我将显示获取的数据或加载屏幕。现在的问题是,每当我更改页面然后重新打开带有数据的屏幕时,在显示加载屏幕之前,react 会在短时间内呈现先前获取的先前状态数据。 希望有人可以向我解释如何避免这种行为以及它这样做的原因。 这是我正在谈论的示例代码。如果我更改路线并返回,我可以看到旧数据:

//App.js
function App() {
    return (
        <BrowserRouter>
            <Header/>
            <Route exact path='/' component={ProductList}/>
            <Route exact path='/NotHome' component={NotHome}/>
        </BrowserRouter>
    );
}
//ProductList.js
const ProductList = (props) => {

    const [Skip, setSkip] = useState(0);
    const [Limit] = useState(5);

    useEffect(() => {
        props.requestProductList(Skip, Limit);
    }, []);

    return (
        props.isLoading
            ? <h1>LOADING</h1>
            : <div>
                {props.productList && props.productList.map(product => (
                    <div key={product._id}>
                        <p>{product.productName}</p>
                        <img src={`http://localhost:5000${product.productMainPicture}`} style={{width: 200, height: 200}}/>
                    </div>
                ))}
            </div>
    )
};

const mapStateToProps = (state) => ({
    productList: state.product.productList,
    isLoading: state.product.isLoading,
});

const actionCreators = {
    requestProductList
};

export default connect(mapStateToProps, actionCreators)(ProductList);
//ProductReducer.js

const PRODUCT_SET_PRODUCT_LIST = 'PRODUCT_SET_PRODUCT_LIST';
const SET_LOADING = 'SET_LOADING';

const initialState = {
    productList: [],
    isLoading: false
}

export const ProductReducer = (state = initialState, action) => {
    switch (action.type) {
        case PRODUCT_SET_PRODUCT_LIST:
            return {
                ...state,
                productList: [...action.productList],
                productsCount: action.productsCount
            }
        case SET_LOADING:
            return {
                ...state,
                isLoading: action.isLoading
            }
        default:
            return state;
    }
};

const setProductList = (productList, productsCount) => ({type: PRODUCT_SET_PRODUCT_LIST, productList, productsCount});
const setLoading = (isLoading) => ({type: SET_LOADING, isLoading});

export const requestProductList = (skip, limit) => async (dispatch) => {
    dispatch(setLoading(true));
    try {
        const res = await productApi.requestProductList(skip, limit);
        dispatch(setProductList(res.data.products));
        dispatch(setLoading(false));
    } catch (e) {
        console.log(e);
        dispatch(setLoading(false));
    }
};

//api.js
export const productApi = {
    async requestProductList(skip, limit) {
        return await Axios.post(`http://localhost:5000/api/product/get_product_list`, {skip, limit});
    }
}

【问题讨论】:

    标签: reactjs react-redux react-hooks fetch


    【解决方案1】:

    离开页面时如何清除数据,然后在重新访问时,一切都应该按预期工作。

    让我解释一下,

    假设您使用 ObjectA = {...} 设置 Redux 状态,然后当您离开该页面时, objectA 仍然存在值,因此它会立即显示这些值。而网络请求是异步的,需要时间来完成promise并更新objectA。

    为了解决这个问题,你可以创建一个 clearAction,它在离开页面时清除 objectA。

    useEffect(() => 
    {
            props.requestProductList(Skip, Limit);
    
           return () =>
           {
             props.clearData()
           }
    
    
    }, []);
    
    
    /* Redux reducers*/
    
    case CLEAR_DATA:
        return {...state, objectA: null}
    

    【讨论】:

    • 非常感谢,它成功了!这种解决方案是常规做法吗?
    • 我会说这取决于你想如何使用状态。就您而言,这是在重新加载或重新访问页面时管理数据的正确方法。
    • 它并不总是有效,因为在 React v16 中,ComponentWillUnmount 在安装任何下一个组件see 后被调用。所以以防万一,当使用相同的状态时,下一页将首先使用错误的数据进行渲染。
    猜你喜欢
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多