React 和 Redux:connect() 到多个组件和最佳实践
React & Redux : connect() to multiple components & best practices
我正在做我的第一个 React/Redux 项目,我有一个小问题。我已阅读文档并观看了 https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist.
上提供的教程
但我还有一个问题。这是关于登录页面。
所以我有一个名为 LoginForm 的展示组件:
components/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;
还有一个名为 Login 的容器组件,它将数据传递到我的组件。使用 react-redux-router,我称这个容器(而不是 presentationnal 组件):
containers/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);
如您所见,我正在使用 redux 提供的 connect
方法来创建我的容器。
我的问题如下:
如果我想让我的登录容器使用多个视图(例如:LoginForm 和 errorList 来显示错误),我需要手动完成(没有连接,因为连接只接受一个参数)。像 :
class Login extends Component {
render() {
return (
<div>
<errorList />
<LoginForm onSubmitLogin={ (id, pass) => dispatch(login(id, pass)) } />
</div>
)
}
}
这是一种不好的做法吗?创建另一个同时使用 errorList 和 LoginForm 的表示组件 (LoginPage) 并创建一个 connect
到 LoginPage 的容器 (Login) 是否更好?
编辑: 如果我创建第三个展示组件 (LoginPage),我将不得不传递两次数据。像这样:Container -> LoginPage -> LoginForm & ErrorList
。
即使有上下文,它似乎也不是要走的路。
我认为您在第二个示例中的内容非常接近。您可以只创建一个连接的容器组件并呈现多个展示组件。
在您的第一个示例中,实际上不是一个单独的容器组件:
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);
尽管它在一个单独的模块中,但您在这里所做的是直接连接您的 LoginForm
。
相反,您可以这样做:
containers/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);
请注意,Login
组件现在被传递给 connect
,使其成为 "container" 组件,然后 errorList
和 LoginForm
都可以表象。他们的所有数据都可以通过 Login
容器的 props 传递。
我坚信您需要将所有组件构建为演示组件。目前您需要一个容器组件,您可以在现有的演示组件之一上使用 {connect} 并将其转换为容器组件。
但是,这只是我目前对 React 经验不足的看法。
我正在做我的第一个 React/Redux 项目,我有一个小问题。我已阅读文档并观看了 https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist.
上提供的教程但我还有一个问题。这是关于登录页面。 所以我有一个名为 LoginForm 的展示组件:
components/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;
还有一个名为 Login 的容器组件,它将数据传递到我的组件。使用 react-redux-router,我称这个容器(而不是 presentationnal 组件):
containers/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);
如您所见,我正在使用 redux 提供的 connect
方法来创建我的容器。
我的问题如下:
如果我想让我的登录容器使用多个视图(例如:LoginForm 和 errorList 来显示错误),我需要手动完成(没有连接,因为连接只接受一个参数)。像 :
class Login extends Component {
render() {
return (
<div>
<errorList />
<LoginForm onSubmitLogin={ (id, pass) => dispatch(login(id, pass)) } />
</div>
)
}
}
这是一种不好的做法吗?创建另一个同时使用 errorList 和 LoginForm 的表示组件 (LoginPage) 并创建一个 connect
到 LoginPage 的容器 (Login) 是否更好?
编辑: 如果我创建第三个展示组件 (LoginPage),我将不得不传递两次数据。像这样:Container -> LoginPage -> LoginForm & ErrorList
。
即使有上下文,它似乎也不是要走的路。
我认为您在第二个示例中的内容非常接近。您可以只创建一个连接的容器组件并呈现多个展示组件。
在您的第一个示例中,实际上不是一个单独的容器组件:
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);
尽管它在一个单独的模块中,但您在这里所做的是直接连接您的 LoginForm
。
相反,您可以这样做:
containers/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);
请注意,Login
组件现在被传递给 connect
,使其成为 "container" 组件,然后 errorList
和 LoginForm
都可以表象。他们的所有数据都可以通过 Login
容器的 props 传递。
我坚信您需要将所有组件构建为演示组件。目前您需要一个容器组件,您可以在现有的演示组件之一上使用 {connect} 并将其转换为容器组件。
但是,这只是我目前对 React 经验不足的看法。