Javascript 根据使用Redux进行的状态更改对事件侦听器进行响应

Javascript 根据使用Redux进行的状态更改对事件侦听器进行响应,javascript,reactjs,redux,react-router,Javascript,Reactjs,Redux,React Router,下午好 当我试图根据状态的变化重定向应用程序的用户时,我在使用React和Redux时遇到了一些困难 在较高的层次上:当我的状态中的用户对象填充了来自home/to/student/:username的信息时,我希望我的应用程序的路径发生改变 现在,我已经以一种骇人的方式完成了这项工作 在我的登录组件中,当第三方API的访问令牌从我的Express服务器传回客户机时,我使用componentDidUpdate生命周期钩子侦听并分派操作 import React from "react"; im

下午好

当我试图根据状态的变化重定向应用程序的用户时,我在使用React和Redux时遇到了一些困难

在较高的层次上:当我的状态中的用户对象填充了来自home/to/student/:username的信息时,我希望我的应用程序的路径发生改变

现在,我已经以一种骇人的方式完成了这项工作

在我的登录组件中,当第三方API的访问令牌从我的Express服务器传回客户机时,我使用componentDidUpdate生命周期钩子侦听并分派操作

import React from "react";

import LoginForm from "../minor/LoginForm";

const Login = React.createClass({

  componentDidUpdate(){
    const {success, access_token} = this.props.loginStatus;

    if (success === true && access_token !== null){
      console.log("It worked getting your data now...");
      this.props.getUserData(access_token);
    } else if (success === false || access_token === null){
      console.log("Something went wrong...");
    } 

  }, 
render(){

    return(

        <div className="loginComponentWrapper">
          <h1>Slots</h1>
          <LoginForm loginSubmit={this.props.loginSubmit}
                     router={this.props.router}
                     user={this.props.user} />
          <a href="/register">New User?</a>
        </div>
      )
  }
});
当然可以,但我确信这是一个过于复杂的解决方案,而不是最佳实践。我曾尝试在我的登录组件中添加一个自定义侦听器方法,但从未成功启动过,相反,我的应用程序陷入了一个循环

有没有一种方法可以使用Redux做到这一点并保持组件整洁,或者以更有效的方式利用componentDidUpdate

和往常一样,我希望能有更多有经验的人关注我的问题,并期待得到一些反馈

谢谢

更新

App.js

这个组件将我所有的redux内容和状态数据洒入名为StoreShell的容器组件中,该组件将所有这些数据传递给组成UI的元素(如Login和LoginForm)的道具。我是否采取了太多步骤

StoreShell.js

如果您使用的是react router版本4.x.x:您可以只呈现一个重定向组件,该组件处理react router文档中的重定向

从React导入React; 从react路由器导入{Redirect}; 从../minor/LoginForm导入LoginForm; const Login=React.createClass{ 组件更新{ const{success,access_token}=this.props.loginStatus; 如果成功===true&&access\u令牌!==null{ console.logIt现在正在获取您的数据。。。; this.props.getUserDataaccess\u令牌; }否则如果成功===false | |访问|令牌===null{ 有什么地方出了问题。。。; } } 渲染{ //如果定义了用户,则重定向到/student/:username 如果this.props.user.username!==null{ 回来 } //否则,请呈现登录表单 回来 槽 } }; 如果您使用的是react router 3.x.x版:您的做法基本上是正确的。我会将重定向从LoginForm组件移动到Login组件;这样,LoginForm就不需要依赖于用户属性

我知道,我也不太喜欢这个图案

希望这有帮助

如果您使用的是react router版本4.x.x:您可以只渲染一个重定向组件,该组件处理react router文档中的重定向

从React导入React; 从react路由器导入{Redirect}; 从../minor/LoginForm导入LoginForm; const Login=React.createClass{ 组件更新{ const{success,access_token}=this.props.loginStatus; 如果成功===true&&access\u令牌!==null{ console.logIt现在正在获取您的数据。。。; this.props.getUserDataaccess\u令牌; }否则如果成功===false | |访问|令牌===null{ 有什么地方出了问题。。。; } } 渲染{ //如果定义了用户,则重定向到/student/:username 如果this.props.user.username!==null{ 回来 } //否则,请呈现登录表单 回来 槽 } }; 如果您使用的是react router 3.x.x版:您的做法基本上是正确的。我会将重定向从LoginForm组件移动到Login组件;这样,LoginForm就不需要依赖于用户属性

我知道,我也不太喜欢这个图案


希望这有帮助

有几种方法可以使登录流更易于管理,并对组件进行一些推理和整理。首先,有几个要点:

我不确定您为什么要在这两个组件之间划分登录逻辑?惯用的React/Redux方法是有一个处理逻辑的容器组件和一个处理表示的表示组件。目前,这两个组件都做了一点

您不需要通过组件上下传递props.router。React router提供了一个HOC,该HOC将路由器作为称为withRouter的道具提供。您只需使用路由器和道具包装一个组件。路由器可用-其他一切保持不变

export default withRouter(LoginForm);
我个人的感觉是URI是应用程序状态的一部分,因此它应该在应用商店中维护,并通过调度操作进行更新。有一个破解库可用于执行此操作-。一旦你有了它的设置,然后你可以通过推方法到你的组件或其他地方。。。请参见下一个要导航的点:

import { push } from 'react-router-redux';
import { connect } from 'react-redux';

const NavigatingComponent = props => (
    <button onClick={() => props.push('/page')}>Navigate</button>
);

const mapStateToProps = null;
const mapDispatchToProps = {
    push
};

export default connect(mapStateToProps, mapDispatchToProps)(NavigatingComponent);
组件所做的唯一事情就是调用初始登录函数,该函数可以实现 比如:

容器:

import React from 'react';
import { connect } from 'react-redux';

import { login } from '../path/to/actionCreators';
import LoginForm from './LoginForm';

const LoginContainer = React.createClass({
    handleSubmit() {
        this.props.login(
           this.usernameInput.value,
           this.passwordInput.value
        );
    },

    setUsernameRef(input) {
        this.usernameInput = input;
    },

    setPasswordRef(input) {
        this.passwordInput = input;
    },

    render() {
        return (
           <LoginForm
              handleSubmit={this.handleSubmit.bind(this)}
              setUsernameRef={this.setUsernameRef.bind(this)}
              setPasswordRef={this.setPasswordRef.bind(this)}
           />
        );
    }
});

const mapStateToProps = null;
const mapDispatchToProps = {
    login
};

export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer);
组成部分:

import React from 'react';

export const LoginForm = ({ handleSubmit, setUsernameRef, setPasswordRef }) => (  
    <div className="loginWrapper">
        <div className="loginBox">
            <form className="loginForm" action="">
                <input ref={setUsernameRef} type="text" placeholder="username" defaultValue="kitties@kit.com" />
                <input ref={setPasswordRef} type="text" placeholder="password" defaultValue="meowMeow3" />
                <button onClick={handleSubmit}>Login</button>
            </form>
        </div>
    </div>
);
这实现了逻辑/数据提供容器和无状态表示组件的分离。LoginForm组件可以简单地作为上述函数编写,因为它不负责处理逻辑。容器也是一个非常简单的组件-在我们的action creator/thunk中,逻辑都是孤立的,更易于阅读和推理


redux thunk只是使用redux管理异步副作用的一种方法——还有许多其他方法。我个人的偏好是对,这可能会让你感兴趣。然而,在我自己的redux之旅中,我肯定从使用和理解redux thunk中获益匪浅,然后才发现它的局限性/缺点并继续前进,我会向其他人推荐这条路线。

有几件事可以让登录流更容易管理,并稍微解释和整理一下您的组件。首先,有几个要点:

我不确定您为什么要在这两个组件之间划分登录逻辑?惯用的React/Redux方法是有一个处理逻辑的容器组件和一个处理表示的表示组件。目前,这两个组件都做了一点

您不需要通过组件上下传递props.router。React router提供了一个HOC,该HOC将路由器作为称为withRouter的道具提供。您只需使用路由器和道具包装一个组件。路由器可用-其他一切保持不变

export default withRouter(LoginForm);
我个人的感觉是URI是应用程序状态的一部分,因此它应该在应用商店中维护,并通过调度操作进行更新。有一个破解库可用于执行此操作-。一旦你有了它的设置,然后你可以通过推方法到你的组件或其他地方。。。请参见下一个要导航的点:

import { push } from 'react-router-redux';
import { connect } from 'react-redux';

const NavigatingComponent = props => (
    <button onClick={() => props.push('/page')}>Navigate</button>
);

const mapStateToProps = null;
const mapDispatchToProps = {
    push
};

export default connect(mapStateToProps, mapDispatchToProps)(NavigatingComponent);
您的组件所做的唯一一件事就是调用初始登录函数,该函数的实现方式如下:

容器:

import React from 'react';
import { connect } from 'react-redux';

import { login } from '../path/to/actionCreators';
import LoginForm from './LoginForm';

const LoginContainer = React.createClass({
    handleSubmit() {
        this.props.login(
           this.usernameInput.value,
           this.passwordInput.value
        );
    },

    setUsernameRef(input) {
        this.usernameInput = input;
    },

    setPasswordRef(input) {
        this.passwordInput = input;
    },

    render() {
        return (
           <LoginForm
              handleSubmit={this.handleSubmit.bind(this)}
              setUsernameRef={this.setUsernameRef.bind(this)}
              setPasswordRef={this.setPasswordRef.bind(this)}
           />
        );
    }
});

const mapStateToProps = null;
const mapDispatchToProps = {
    login
};

export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer);
组成部分:

import React from 'react';

export const LoginForm = ({ handleSubmit, setUsernameRef, setPasswordRef }) => (  
    <div className="loginWrapper">
        <div className="loginBox">
            <form className="loginForm" action="">
                <input ref={setUsernameRef} type="text" placeholder="username" defaultValue="kitties@kit.com" />
                <input ref={setPasswordRef} type="text" placeholder="password" defaultValue="meowMeow3" />
                <button onClick={handleSubmit}>Login</button>
            </form>
        </div>
    </div>
);
这实现了逻辑/数据提供容器和无状态表示组件的分离。LoginForm组件可以简单地作为上述函数编写,因为它不负责处理逻辑。容器也是一个非常简单的组件-在我们的action creator/thunk中,逻辑都是孤立的,更易于阅读和推理


redux thunk只是使用redux管理异步副作用的一种方法——还有许多其他方法。我个人的偏好是对,这可能会让你感兴趣。然而,在我自己的redux之旅中,我肯定从使用和理解redux thunk中获益匪浅,然后才发现它的局限性/缺点并继续前进,我会向其他人推荐这条路线。

非常感谢,我不知道react router 4.x.x可用!我要调查一下,看看它对我的项目有什么好处。我感谢您的回答,因为我可以在自己的代码中看到解决方案。原来我使用的是react router 3.0.1,也许是时候更新了……非常感谢,我不知道react router 4.x.x可用!我要调查一下,看看它对我的项目有什么好处。我感谢您的回答,因为我可以在自己的代码中看到解决方案。事实证明,我使用的是react router 3.0.1,也许是时候更新了……事实上,我刚刚开始采用redux,我感谢您的回复,因为我认为我更了解redux的用途。我喜欢URI作为状态的一部分,我认为这是一个明智的做法。我有在这个项目中使用redux thunk的经验,现在将扩展我的使用范围。这里有很多很棒的东西,我很感谢你的全面回复。一个问题:为什么连接与mapStateToProps和mapDispatchToProps一起使用在登录组件的底部?我在登录上面的另一个容器组件中执行此操作。我将更新我的问题以向您展示。我连接了LoginContainer,因为对我来说,这是最好的地方。虽然可以将登录actioncreator作为一个道具从树上更高的连接组件传递,但这只会给我增加不必要的复杂性。它还损害了组件的易重用性。即,当连接LoginContainer时。如果您想在站点的其他位置放置另一个登录组件,那么您所需要做的就是导入并呈现它。如果一个父组件负责连接,那么每次你想重新使用它时,你都必须连接它的父组件。这对我来说是有意义的,因为我的组件被很多道具和分派器污染了,例如Login,它是我的LoginForm容器。基于此讨论,我似乎可以摆脱上面的App.js组件,不是吗?是的,当您在每个组件级别导入和连接所需的部分时,应用组件的连接变得不必要。这
是构造了多少个React/Redux应用程序-每个容器导入mapDispatchToProps所需的动作创建者,他们需要使用选择器的状态请查看MapStateTops的重新选择库。实际上,我刚刚开始采用redux,我感谢您的回复,因为我认为我更了解redux的用途。我喜欢URI作为状态的一部分,我认为这是一个明智的做法。我有在这个项目中使用redux thunk的经验,现在将扩展我的使用范围。这里有很多很棒的东西,我很感谢你的全面回复。一个问题:为什么连接与mapStateToProps和mapDispatchToProps一起使用在登录组件的底部?我在登录上面的另一个容器组件中执行此操作。我将更新我的问题以向您展示。我连接了LoginContainer,因为对我来说,这是最好的地方。虽然可以将登录actioncreator作为一个道具从树上更高的连接组件传递,但这只会给我增加不必要的复杂性。它还损害了组件的易重用性。即,当连接LoginContainer时。如果您想在站点的其他位置放置另一个登录组件,那么您所需要做的就是导入并呈现它。如果一个父组件负责连接,那么每次你想重新使用它时,你都必须连接它的父组件。这对我来说是有意义的,因为我的组件被很多道具和分派器污染了,例如Login,它是我的LoginForm容器。基于此讨论,我似乎可以摆脱上面的App.js组件,不是吗?是的,当您在每个组件级别导入和连接所需的部分时,应用组件的连接变得不必要。这是构造的React/Redux应用程序的数量-每个容器导入mapDispatchToProps所需的操作创建者,以及使用选择器所需的状态查看MapStateTrops的重新选择库。