我的问题和标题一样。
假设我写了以下代码。
class TODOList extends Component {
render() {
const {todos, onClick} = this.props;
return (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
onClick={onClick}
{...todo}
/>
)}
</ul>
);
}
}
const mapStateToProps = (state) => {
return {
todos: state.todos
}
}
const mapDispatchToProps = (dispatch) => {
return {
onClick(data){
dispatch(complete(data))
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(TODOList);
现在,在最后一行之后,此代码将导出状态为道具的TODOList组件。并不是说它包含状态,而是只是接收到状态,并将其作为“属性”,就像方法名“ mapStateToProps”所说明的那样。
在Dan Abramov撰写的中篇文章(https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0)中,容器组件将数据作为状态来处理,而presentational属性作为道具来处理。它不是将数据作为道具处理的表示性组件吗?我坚持认为正确的容器应为以下容器。
class CommentList extends React.Component {
this.state = { comments: [] };
componentDidMount() {
fetchSomeComments(comments =>
this.setState({ comments: comments }));
}
render() {
return (
<ul>
{this.state.comments.map(c => (
<li>{c.body}—{c.author}</li>
))}
</ul>
);
}
}
当我尝试使“有状态”(不按属性处理数据)容器组件时,我不确定为什么react-redux将API命名为“ mapStateToProps”
答案 0 :(得分:10)
首先,这些指南不是圣经的一部分
您应该编写易于理解的 YOU和您的TEAM 代码。
我认为您缺少了一些东西,redux容器与react容器不同。
我的意思是,connect
将为您创建容器,这并不意味着包装的组件是一个容器。
基本上,您可以从同一文件中导出两个版本,即容器(连接的版本)和演示文稿版本(不连接的版本)。
通常会使人失望的另一件事是mapStateToProps
的函数名称和参数。
我更喜欢mapStoreToProps
的名称,如
将
redux
存储区映射到组件的props。
在state
的上下文中,名称react
可能会造成混淆。
修改
作为您评论的后续内容:
我完全不知道这两个实际上是不同的。你能告诉我更多细节吗?
connect
为您创建“容器”的方式有所不同。
connect
是一个高级组件,它为我们创建了Container Component,具有所有订阅逻辑+函数,以将部分商店和动作创建者作为道具({{1} }和mapStateToProps
。
“普通”容器通常是指您用手工编写的组件,它通常不处理外观,而是处理应用程序的某些逻辑。
关于其他评论,例如
react-redux的connect HoC只是将您可以请求的属性注入到组件中。它返回一个包裹在您的组件周围的新组件,以便在您对redux存储感兴趣的状态被修改时可以更新您的组件
如上所述,这部分是正确的。这不仅是将属性注入到我们的组件中,它还可以订阅商店,从mapDispatchToProps
(通过Provider
抓取),并且在进行所有这些操作时都考虑了优化,因此我们不必自己做。
我不确定mapStateToProps如何使某人困惑。我们正在谈论一个状态管理库
我看到一些开发人员误解了这一点,因为context
有一个react
,而state
有一个redux
(至少在大多数情况下就是这样教程和文档)。
这可能会使一些刚接触store
或react
的人感到困惑。
编辑2
由于这句话“这并不意味着包装的组件是容器”,这有点令人困惑。为什么包装的组件不是容器?不是通过connect创建的组件也是容器吗?
我的意思是您编写的包装组件不必是一个容器。
您可以连接“演示文稿”组件:
redux
答案 1 :(得分:2)
mapStateToProps
。它将把返回的对象作为组件的新道具传递。这不会影响组件的状态。如果您想在组件获得新道具后设置新状态,则需要使用另一种生命周期方法:static getDerivedStateFromProps
(在早期版本的react componentWillRecieveProps
中)。 static getDerivedStateFromProps
返回的对象将是您的新状态。
https://reactjs.org/docs/state-and-lifecycle.html#adding-lifecycle-methods-to-a-class
connect()
会将您的组件连接到redux存储。没有连接功能(当然),您的mapStateToProps
将无法工作。
我不确定为什么react-redux将API命名为“ mapStateToProps”
我们正在谈论商店的状态:)
答案 2 :(得分:0)
高级目的是将Redux的状态管理无缝集成到React应用程序中。 Redux围绕着所有状态都存在的商店。除了通过还原者(它从动作创建者那里接收动作)接收到的现金以外,没有其他方法可以直接修改商店。为此,我们需要从动作创建者中分发动作。
connect()
函数通过获取Redux存储中的状态并将其映射到prop
中,将我们的组件直接连接到Redux存储。
这是Redux的强大功能以及我们使用它的原因。
可以说您正在构建一个名为LaundryList
的组件,并且希望它呈现一个洗衣清单。在将Provider
连接到“父”组件中之后,我将其用引号引起来,因为从技术上讲,Provider
是一个组件,因此它成为父组件。
然后,您可以从connect()
导入react-redux
函数,并将其传递给mapStateToProps
,以便从Redux商店中获取该洗衣清单到您的LaundryList
组件中。
现在,您在LaundryList
组件中有了亚麻布清单,您可以开始着重于从其中构建元素清单,如下所示:
class LaundryList extends Component {
render() {
console.log(this.props.linens);
return <div>LaundryList</div>;
}
}
其中包含亚麻布对象列表,对于其中的每个亚麻布列表,我们将返回一些jsx来表示我的亚麻布列表。
回到洗衣清单组件内部,我将在洗衣清单组件内部添加一个名为render list的帮助方法,如下所示:
class LaundryList extends Component {
renderList() {
}
render() {
return <div>LaundryList</div>;
}
}
因此,此辅助方法的目的是获取亚麻布的列表,在它们上进行映射,然后像这样返回大的jsx斑点:
class LaundryList extends Component {
renderList() {
return this.props.linens.map((linen) => {
return (
);
});
}
render() {
return <div>LaundryList</div>;
}
}