简体   繁体   English

React&Redux:connect()到多个组件和最佳实践

[英]React & Redux : connect() to multiple components & best practices

I'm working on my first React/Redux project and I have a little question. 我正在研究我的第一个React / Redux项目,我有一个小问题。 I've read the documentation and watched the tutorials available at https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist . 我已经阅读了文档,并在https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist上查看了这些教程。

But I still have one question. 但我还有一个问题。 It's about a login page. 这是一个登录页面。 So I have a presentational component named LoginForm : 所以我有一个名为LoginForm的表示组件:

components/LoginForm.js 组件/ LoginForm.js

import { Component, PropTypes } from 'react'

class LoginForm extends Component {
   render () {
      return (
         <div>
            <form action="#" onSubmitLogin={(e) => this.handleSubmit(e)}>
               <input type="text" ref={node => { this.login = node }} />
               <input type="password" ref={node => { this.password = node }} />
               <input type="submit" value="Login" />
            </form>
         </div>
      )
   }

   handleSubmit(e) {
      e.preventDefault();
      this.props.onSubmitLogin(this.login.value, this.password.value);
   }
}

LoginForm.propTypes = {
   onSubmitLogin: PropTypes.func.isRequired
};

export default LoginForm;

And a container component named Login which pass data to my component. 还有一个名为Login的容器组件,它将数据传递给我的组件。 Using react-redux-router, I call this container (and not the presentationnal component) : 使用react-redux-router,我称之为容器(而不是presentationnal组件):

containers/Login.js 集装箱/ Login.js

import { connect } from 'react-redux'
import { login } from '../actions/creators/userActionCreators'
import LoginForm from '../components/LoginForm'

const mapDispatchToProps = (dispatch) => {
   return {
      onSubmitLogin: (id, pass) => dispatch(login(id, pass))
   }
};

export default connect(null, mapDispatchToProps)(LoginForm);

As you can see, I'm using the connect method provide by redux to create my container. 如您所见,我正在使用redux提供的connect方法来创建我的容器。

My question is the following one : 我的问题是以下一个:

If I want my Login container to use multiple views (for example : LoginForm and errorList to display errors), I need to do it by hand (without connect because connect take only one argument). 如果我希望我的Login容器使用多个视图(例如:LoginForm和errorList来显示错误),我需要手动完成(没有连接,因为connect只接受一个参数)。 Something like : 就像是 :

class Login extends Component {

   render() {
      return (
         <div>
            <errorList />
            <LoginForm onSubmitLogin={ (id, pass) => dispatch(login(id, pass)) } />
         </div>
      )
   }

}

Is it a bad practice ? 这是一种不好的做法吗? Is it better to create another presentational component (LoginPage) which use both errorList and LoginForm and create a container (Login) which connect to LoginPage ? 是否更好地创建另一个同时使用errorList和LoginForm的表示组件(LoginPage)并创建一个connect到LoginPage的容器(Login)?


EDIT: If I create a third presentational component (LoginPage), I'll have to pass data twice. 编辑:如果我创建第三个表示组件(LoginPage),我将不得不传递两次数据。 Like this : Container -> LoginPage -> LoginForm & ErrorList . 像这样: Container -> LoginPage -> LoginForm & ErrorList Even with context, it don't seems to be the way to go. 即使有上下文,它似乎也不是要走的路。

I think that what you have in your second example is very close. 我认为你在第二个例子中的内容非常接近。 You can create just one container component that's connected and render multiple presentational components. 您只能创建一个连接的容器组件并呈现多个表示组件。

In your first example, there actually isn't a separate container component: 在您的第一个示例中,实际上没有单独的容器组件:

import { connect } from 'react-redux'
import { login } from '../actions/creators/userActionCreators'
import LoginForm from '../components/LoginForm'

const mapDispatchToProps = (dispatch) => {
   return {
      onSubmitLogin: (id, pass) => dispatch(login(id, pass))
   }
};

// `LoginForm` is being passed, so it would be the "container"
// component in this scenario
export default connect(null, mapDispatchToProps)(LoginForm);

Even though it's in a separate module, what you're doing here is connecting your LoginForm directly. 即使它是在一个单独的模块中,你在这里做的是直接连接你的LoginForm

Instead, what you can do is something like this: 相反,你可以做的是这样的:

containers/Login.js 集装箱/ Login.js

import { connect } from 'react-redux'
import { login } from '../actions/creators/userActionCreators'
import LoginForm from '../components/LoginForm'
import ErrorList from '../components/ErrorList'

class Login extends Component {

   render() {
      const { onSubmitLogin, errors } = this.props;

      return (
         <div>
            <ErrorList errors={errors} />
            <LoginForm onSubmitLogin={onSubmitLogin} />
         </div>
      )
   }

}

const mapDispatchToProps = (dispatch) => {
   return {
      onSubmitLogin: (id, pass) => dispatch(login(id, pass))
   }
};

const mapStateToProps = (state) => {
   return {
       errors: state.errors
   };
};

export default connect(mapStateToProps, mapDispatchToProps)(Login);

Note that the Login component is now being passed to connect , making it the "container" component and then both the errorList and LoginForm can be presentational. 请注意, Login组件现在被传递给connect ,使其成为“容器”组件,然后errorListLoginForm都可以呈现。 All of their data can be passed via props by the Login container. 所有数据都可以通过Login容器通过props传递。

I truly believe that you need to build all your components as Presentational Components. 我真的相信你需要将所有组件构建为演示组件。 At the moment you need a Container Component, you might use {connect} over one of the existing Presentational and convert into a Container one. 目前您需要一个容器组件,您可以在现有的一个演示文稿上使用{connect}并转换为一个容器组件。

But, that is only my view with short experience in React so far. 但是,到目前为止,这只是我对React经验不足的看法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM