请求完成后触发 Redux 异步操作。为啥?

Posted

技术标签:

【中文标题】请求完成后触发 Redux 异步操作。为啥?【英文标题】:Redux async action triggered after request finished. Why?请求完成后触发 Redux 异步操作。为什么? 【发布时间】:2017-09-12 10:54:00 【问题描述】:

我的异步操作有问题。我想在调用操作 fetchPosts() 时将“加载”状态设置为 true,而在操作 fetchPostsSuccess() 或 fetchPostsFailiure() 时将“加载”状态设置为 false。

使用我当前的代码,它几乎可以正常工作,除了当 fetchPosts() 接收到来自服务器的响应时“正在加载”状态发生变化,我想在请求开始时更改此状态。

这是显示我的步骤的简单代码。 我正在使用 axios 和 redux-promise (https://github.com/acdlite/redux-promise)。

// actions
export function fetchPosts() 
  const request = axios.get(`$API_URL/posts/`);
  return 
    type: 'FETCH_POSTS',
    payload: request,
  ;


export function fetchPostsSuccess(posts) 
  return 
    type: 'FETCH_POSTS_SUCCESS',
    payload: posts,
  ;


export function fetchPostsFailure(error) 
  return 
    type: 'FETCH_POSTS_FAILURE',
    payload: error,
  ;



// reducer
const INITIAL_STATE = 
  posts: [],
  loading: false,
  error: null,

const postsReducer = (state = INITIAL_STATE, action) => 
  switch (action.type) 
    case 'FETCH_POSTS':
      return  ...state, loading: true, error: null ;
    case 'FETCH_POSTS_SUCCESS':
      return  ...state, posts: action.payload, loading: false ;
    case 'FETCH_POSTS_FAILURE':
      return  ...state, posts: [], loading: false, error: action.payload ;
    default:
      return state;
  


const rootReducer = combineReducers(
  postsList: postsReducer,
);


// store
function configureStore(initialState) 
  return createStore(
    rootReducer,
    applyMiddleware(
      promise,
    ),
  );

const store = configureStore();


// simple Posts app
class Posts extends Component 
  componentWillMount() 
    this.props.fetchPosts();
  

  render() 
    const  posts, loading  = this.props.postsList;
    return (
      <div>
        loading && <p>Loading...</p>
        <ul>
          posts.map(post => <li key=post.id>post.title</li>)
        </ul>
      </div>
    );
  


const mapStateToProps = state => (
  postsList: state.postsList,
);

const mapDispatchToProps = dispatch => (
  fetchPosts: (params = ) => 
    dispatch(fetchPosts())
      .then((response) => 
        if (!response.error) 
          dispatch(fetchPostsSuccess(response.payload.data));
         else 
          dispatch(fetchPostsFailure(response.payload.data));
        
      );
  ,
);


const PostsContainer = connect(mapStateToProps, mapDispatchToProps)(Posts);

// main
ReactDOM.render((
  <Provider store=store>
    <Router history=browserHistory>
      <Route path="posts" component=PostsContainer />
    </Router>
  </Provider>
), document.getElementById('appRoot'));

有人可以指导我做错了什么吗?

【问题讨论】:

【参考方案1】:

原来问题出在“redux-promise”包上。这个异步中间件没有“待定”承诺状态(称为“乐观更新”)之类的东西。

只有在 promise 被解决或拒绝时才会改变状态。

我应该使用允许“乐观更新”的不同中间件

【讨论】:

【参考方案2】:

您的问题在于redux-promise。您应该使用redux-thunk 来代替它允许您返回一个函数并多次分派。看看吧;)!

【讨论】:

谢谢,确实是 redux-promise 的问题。我发现 redux-promise-middleware 是我需要的。

以上是关于请求完成后触发 Redux 异步操作。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

Redux thunk:如何等待异步操作的完成

React Redux 中触发异步副作用

React Redux 中触发异步副作用

一种使用 createAsyncThunk 触发多个异步操作的简洁方法

Redux - 异步 - 输入字段更改时的 POST 状态

为啥说nodejs是异步非阻塞