Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带Redux的异步操作_Javascript_Reactjs_Redux - Fatal编程技术网

Javascript 带Redux的异步操作

Javascript 带Redux的异步操作,javascript,reactjs,redux,Javascript,Reactjs,Redux,我有一个连接到Redux商店的React组件。我在组件willmount生命周期方法中获取资源(帖子) componentWillMount() { this.props.fetchPosts(); } 组件将订阅Redux store并从该store获取isFetching和posts const mapStateToProps = (state) => { return { posts: getAllPosts(state), isFetching: getI

我有一个连接到Redux商店的React组件。我在
组件willmount
生命周期方法中获取资源(帖子)

componentWillMount() {
  this.props.fetchPosts();
}
组件将订阅Redux store并从该store获取
isFetching
posts

const mapStateToProps = (state) => {
  return {
    posts: getAllPosts(state),
    isFetching: getIsFetchingPosts(state),
  }
}
我想在微调器仍在抓取时显示它,因此在
render
方法中我想这样做

render() {
   if (this.props.isFetching) {
     return <Spinner />
   }

   return this.props.posts.map(post => <PostItem key={post.id}{...post}/>)
}

提前谢谢你

简单的回答是,考虑到您的实现,这是预期的行为。您正在将
isFetching
状态映射到一个道具。下面是正在发生的事情:

  • 状态树中的
    isFetching
    的初始值为
    false
    ,因此
    isFetching
    属性值为
    false
    ,因此呈现为
    false

  • 您调度一个操作,该操作将状态树中的
    isFetching
    更改为
    true
    。此新状态映射到一个新的
    isFetching
    prop值
    true
    ,该值会导致重新渲染,并在其中渲染为
    true

  • 您(异步)调度另一个操作,将状态树中的
    isFetching
    更改回
    false
    。与(2)中相同,这会导致重新渲染,
    isFetching
    false

  • 如果您只想在当前实现中呈现
    true,false
    *,那么简单的解决方案是在还原程序的初始状态下将
    isFetching
    设置为
    true

    对于这个组件来说,这个实现在设计层面上是否有意义是一个更广泛的问题,这里没有足够的上下文来回答:-)

    *update为了完整起见,我应该说我不知道
    render()
    函数是否会被调用两次,在这种情况下,
    isFetching
    解析为
    true,false
    ,或者调用
    true,true,false
    三次。我怀疑react-redux可能会优化组件的渲染,这样,如果映射的
    正在获取
    属性从
    true
    ->
    true
    更改,则不会发生重新渲染,但我不确定这一点-如果您能让我知道您的日志输出,我将不胜感激并感兴趣


    在任何情况下,由于标准的react virtual DOM diffing优化,在DOM级别上肯定只会发生两次渲染,因此实际上结果是相同的

    不太清楚fetchPosts是什么,您不在MapStateTops中提供它。来自state的post和fetchPosts之间的连接是什么(函数是否更新state?)。你能澄清一下吗?在开始时使用
    isFetching=false
    是一个不错的行为,因为这只意味着操作还没有到达减速机,ie
    render
    是在
    fetchPosts
    将标志设置为true之前调用的。谢谢你的回答!我刚刚更新了问题。“理想情况下,当此容器第一次呈现时,isFetching state已设置为true并显示微调器。我需要进行哪些更改才能实现此目的?”您对此有何想法?顺便说一句,我正在使用反应路由器。没问题。老实说,这是我在自己的减速器设计中一直在努力解决的问题——如何保持初始状态,并为组件的每个新渲染重置该初始状态。您可以设置初始状态,使
    isFetching
    为true,然后在后续渲染此组件之前,确保在状态树中将其重置为
    true
    。这可能有点费力,取决于您的设计。另一个更简单的方法是保持
    isFetching
    作为组件的内部状态,每次使用getInitialState()安装组件时重置它(cont)。我认为这确实是没有明确答案的设计选择之一。这取决于你的应用程序:-)对于我来说,正如我所说的,在使用redux编写应用程序时,将这些小的、自包含的UI状态保存在哪里是一个大的开放问题。
    /*** Action Creator ***/
    export const fetchPosts = () => (dispatch) => {
      dispatch({
        type: REQUEST_POSTS,
      });
    
      return axios({
        method: 'get',
        url: `${API_URL}/posts`,
      })
      .then(({data}) => {
        dispatch({
          type: RECEIVE_POSTS,
          payload: data.posts,
        })
      })
      .catch((response) => {
        // some error handling.
      });
    }
    
    
    /*** Reducers ***/
    const initialState = {
      isFetching: false,
      allIds: [],
      byId: {},
    };
    
    const isFetching = (state = initialState.isFetcthing, action) => {
      switch (action.type) {
        case REQUEST_POSTS:
          return true;
        case RECEIVE_POSTS:
          return false;
        default:
          return state;
      }
    }
    
    const allIds = (state = initialState.allIds, action) => {
      switch (action.type) {
        case RECEIVE_POSTS:
          return action.payload.map(post => post.id);
        default:
          return state;
      }
    }
    
    const byId = (state = initialState.byId, action) => {
      switch (action.type) {
        case RECEIVE_POSTS:
          return action.payload.reduce((nextState, post) => {
            nextState[post.id] = post;
            return nextState;
          }, {...state});
        default:
          return state;
      }
    }
    
    const posts = combineReducers({
      isFetching,
      allIds,
      byId,
    });
    
    export default posts;
    
    
    /*** Selectors in 'posts.js' file ***/
    
    export const getAllPosts = (state) => {
      const { allId, byId } = state;
      return allIds.map(id => byId[id]);
    }
    
    /*** rootReducer file ***/
    import posts, * as fromPosts from './posts';
    
    
    const rootReducer = combineReducers({
      posts,
    })
    
    export default rootReducer;
    
    export const getAllPosts = (state) => {
      return fromPosts.getAllPosts(state.posts);
    };