如何等待一个动作完成?

Posted

技术标签:

【中文标题】如何等待一个动作完成?【英文标题】:How to wait for an action to complete? 【发布时间】:2017-06-22 15:41:41 【问题描述】:

我是reactredux 的新手,一直在探索它与angular 的不同之处。

我正在尝试做一个简单的登录页面,但无法实现我想要的。从登录表单中获取用户名和密码后,我将其提交如下:

  submitHandler(e)
    e.preventDefault();
    var user = 
      name : this.state.username,
      password: this.state.password
    
    this.props.authenticateUser(user);
    browserHistory.push('/home');
    this.setState(
      username:'',
      password:''
    )
  

这里,authenticateUser 是我的 reducer(如下所示)中的一个函数,它从已经存在的用户列表中检查,然后是带有属性 isAuthenticated 的状态:

 case 'AUTHENTICATE_USER':
        var users = state.userslist;
        var payloadUser = action.payload;
        for (let i = 0; i < users.length; i++) 
            let user = users[i]
            if (user.name === payloadUser.name) 
                return ...state, isAuthenticated: true ;
            
        ;
        return ...state, isAuthenticated: false ;

现在在 Angular 中,我将等待此调用完成并检查此值是 true 还是 false,然后使用 angular-router 导航到主页。

但是我如何在react 中实现同样的效果。我在示例应用程序中使用react-router

我试图在我调用this.props.authenticateUser(user)submitHandler 函数下方检查isAuthenticated,但问题是,this.props.isAuthenticateUser 未更新并返回false,我已将其设置为@987654340 @ 在我的减速器中。

请告诉我在调用authenticateUser 函数后如何检查isAuthenticated,以便我可以继续我的主页路由。我是否必须使用promise 并等待redux 更新状态然后再次检查? (我知道 react 是一种单向路径,但它不会那样工作。)

此外,如果我的身份验证失败,如何在我的登录表单下方显示一个错误面板。我认为为错误面板使用一个组件,该组件以isAuthenticated 作为输入并检查是否为 false 以显示 (即 ngShow 就像在 Angular 中一样。) 但恐怕这行不通同样,因为我的状态不会及时更新。

我知道渲染函数会在状态发生任何变化时被调用。但我就是无法清楚地了解 React。

编辑:为简洁起见,我没有提供上面的动作创建者和完整的减速器,而只显示了身份验证用户的 switch case 操作。我的应用程序遵循原始的 redux 架构,包括操作、reducers、容器、组件等。

编辑: Github 链接here

【问题讨论】:

github.com/V1cHu/react-redux 这个网址转到 404 页面。你能分享正确的网址吗 【参考方案1】:

我更喜欢这样的代码:

const mapStateToProps = (state) => 
  return 
      isAuthenticated: state.isAuthenticated
  


class Dashboard extends PureComponent 
  render() 
    const  isAuthenticated  = this.props

    return (
      <div>
         isAuthenticated ? (
          <div>
            <p>Hello</p>
          </div>
        ) : (
          Login()
        )
      </div>
    )
  

来源:https://***.com/a/56899814/3850405

除了@Nupur 的答案。 componentWillReceiveProps() 被认为是不安全的,方法名称现在是:UNSAFE_componentWillReceiveProps()

https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops

如果您喜欢这种方法,请改用componentDidUpdate(),初始渲染不会调用此方法。

componentDidUpdate(prevProps) 
    if (this.props.isAuthenticated ) 
        //perform code here
    

https://reactjs.org/docs/react-component.html#componentdidupdate

【讨论】:

【参考方案2】:

我将尝试简要解释数据流在 Redux 应用程序中的工作原理:

    不应直接从组件调用 reducer。您对身份验证用户的调用应该在一个操作中,并且应该从组件中分派。

    定义动作时,可以给一个属性来定义动作的类型。例如,在这种情况下,它可能是type: AUTHENTICATE_USER

    action 完成后,redux store 用当前 state 和 action 调用 reducer where。这里可以根据action.type更新redux状态(上面第二个代码sn-p)

    这是最重要的部分:您的组件需要有一个 mapStateToProps 方法,该方法将 Redux 状态中的值作为 props 传递到您的组件中。因此,随着状态的变化,道具会更新并且组件会重新渲染。要使用mapStateToProps,您需要从 react-redux 库中实现连接。 (https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)

为了实现你想要的,这是我的建议:

    在组件的componentWillReceiveProps 方法中,检查props.isAuthenticated 并使用context.router.push() 导航用户是否已通过身份验证。

    还在组件的render 方法中基于props.isAuthenticated 进行检查以显示错误消息。

一些可能有用的链接:

https://redux.js.org/basics/data-flow

https://redux.js.org/basics/usage-with-react

【讨论】:

我确实有 mapStateToProps ,这是我注入 isAuthenticated 的地方,但问题是我不知道何时以及如何在发送操作后检查。因为在调用 isAuthenticated 之后立即检查 isAuthenticated,所以我没有定义。状态不会立即更新。 在正确设置的 Redux 应用程序中,一旦您收到响应并调用 reducer,状态就会更新。通过查看您的代码,我可能会为您提供更多帮助。你可能在 Gihub 上有它吗? 我现在正在工作。将代码推送到 github 并在我回家后与您分享链接。 我已经用代码链接编辑了问题。请帮忙。 我只是看了你的代码,我仍然坚持我之前的两个建议。 login-form.js 组件中的componentWillReceiveProps 方法将跟踪对道具的更改,您可以基于props.isAuthenticated 进行重定向。更多信息在这里:facebook.github.io/react/docs/…

以上是关于如何等待一个动作完成?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 redux-saga 中等待另一个动作

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

在调用另一个动作创建者之前等待动作创建者完成 - Redux thunk

登录方法在推送路由之前不等待调度动作完成

Redux - 如何调用一个动作并等待它解决

Qt如何使用模态(exec())实现等待效果,并同时进行其他操作?(先显示等待,再进行其他操作!)