【问题标题】:Redux useSelect doesn't get updated as expectedRedux useSelect 未按预期更新
【发布时间】:2021-06-03 13:22:30
【问题描述】:

我正在做一个小的概念验证项目,使用 React 和 Redux,以及 useSelector 和 useDispatch 钩子。我正在尝试异步获取一些数据,为此我使用了 thunk。我想我在概念上遗漏了一些东西。即使我的状态按预期工作,我也无法使用 useSelector 从 api 获取数据。

这里是代码。我的行动:

import axios from "axios";

export const API_FETCH_POSTS = 'API_FETCH_POSTS';

export const fetchPosts = (postId) => { // to simulate post request
    return (dispatch) => {

        let baseUrl = 'https://jsonplaceholder.typicode.com/';
        let postFix = 'comments?postId=';
        let url = `${baseUrl}${postFix}${postId}`;

        axios.get(url)
            .then(response => {
                const data = response.data;
                console.log(JSON.stringify(data)); // work!
                dispatch(fetchPostsSuccess(data));
            });
    }
};

const fetchPostsSuccess = posts => {
    return {
        type: API_FETCH_POSTS,
        payload: posts
    }
};

我的减速机:

import {API_FETCH_POSTS} from "./apiActions";

const initialState = {
    getPostsReq : {
        posts: [],
    }
};

const apiReducer = (state = initialState, action) => {
    let getPostsReq;
    switch (action.type) {
        case API_FETCH_POSTS:
            getPostsReq = {
                posts: [...state.getPostsReq.posts]
            };

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

export default apiReducer;

还有rootReducer:

import {combineReducers} from 'redux';
import apiReducer from "./api/apiReducer";

export default combineReducers({
    api: apiReducer
})

并存储:

const initialState = {};

const store = createStore(
    rootReducer,
    initialState,
    composeWithDevTools(
        applyMiddleware(thunk)
    )
);

export default store;

我的 React 组件有问题:

function PostContainer(props) {
    const posts = useSelector(state => state.api.getPostsReq.posts);
    const dispatch = useDispatch();

    const logPosts = () => {
        {/*why doesn't this line work???*/}
        console.log(JSON.stringify(posts));
    }

    return (
        <div>
            <button onClick={() => {
                dispatch(fetchPosts(1));
                logPosts();
            }}>Fetch Posts</button>

            <div>
                {/*why doesn't this line work???*/}
                {posts.map(post => <p>{post.body}</p>)}
            </div>
        </div>
    );
}

export default PostContainer;

我希望在我按下按钮后,函数 fetchPosts 会被调度,因为我使用 thunk 我不应该有任何异步问题。但由于某种原因,我无法使用useSelector() 钩子获取我的状态。我既不能渲染状态,也不能在控制台中记录它。

我在这里错过了什么?

如果方便的话,这里是整个代码 - https://github.com/JavavaJ/use-select-problem

【问题讨论】:

    标签: javascript reactjs asynchronous redux redux-thunk


    【解决方案1】:

    问题:不存储帖子

    你的选择器很好,问题出在你的减速器上!你调度了一个动作,它在payload 中有一个array 的帖子:

    const fetchPostsSuccess = posts => {
        return {
            type: API_FETCH_POSTS,
            payload: posts
        }
    };
    

    但是当您在 reducer 中响应此操作时,您会完全忽略 payload,而只是返回您已经拥有的相同帖子:

    const apiReducer = (state = initialState, action) => {
        let getPostsReq;
        switch (action.type) {
            case API_FETCH_POSTS:
                getPostsReq = {
                    posts: [...state.getPostsReq.posts]
                };
    
                return {
                    ...state,
                    getPostsReq
                };
            default: return state;
        }
    };
    

    解决方案:从 Action 添加帖子

    您可以像这样重写您的 reducer,以使用 Redux immutable update patterns 附加帖子。

    const apiReducer = (state = initialState, action) => {
      switch (action.type) {
        case API_FETCH_POSTS:
          return {
            ...state,
            getPostsReq: {
                ...state.getPostsReq,
                posts: [...state.getPostsReq.posts, ...action.payload]
            }
          };
        default:
          return state;
      }
    };
    

    如果您使用Redux Toolkit 会容易得多!使用该工具包,您可以“改变”您的 reducer 中的草稿状态,因此我们不需要复制所有内容。

    const apiReducer = createReducer(initialState, {
      [API_FETCH_POSTS]: (state, action) => {
        // use ... to push individual items separately
        state.getPostsReq.posts.push(...action.payload);
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2021-11-06
      • 2020-08-30
      • 2021-11-22
      • 2018-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多