我试图理解react-redux的连接方法,以及它作为参数的函数。特别是mapStateToProps()。
我理解它的方式,mapStateToProps的返回值将是一个从状态派生的对象(因为它存在于存储中),它的键将作为道具传递给您的目标组件(组件连接被应用到)。
这意味着目标组件使用的状态可能与存储在存储库中的状态具有完全不同的结构。
问:这样可以吗? 问:这是预期的吗? 问:这是反模式吗?
我试图理解react-redux的连接方法,以及它作为参数的函数。特别是mapStateToProps()。
我理解它的方式,mapStateToProps的返回值将是一个从状态派生的对象(因为它存在于存储中),它的键将作为道具传递给您的目标组件(组件连接被应用到)。
这意味着目标组件使用的状态可能与存储在存储库中的状态具有完全不同的结构。
问:这样可以吗? 问:这是预期的吗? 问:这是反模式吗?
当前回答
是的,这是正确的。它只是一个帮助函数,有一个更简单的方法来访问你的状态属性
假设你在App state.posts中有一个posts键
state.posts //
/*
{
currentPostId: "",
isFetching: false,
allPosts: {}
}
*/
和组件职位
默认情况下,connect()(Posts)将使连接组件的所有状态道具可用
const Posts = ({posts}) => (
<div>
{/* access posts.isFetching, access posts.allPosts */}
</div>
)
现在当你绘制州地图。post到你的组件会更好一些
const Posts = ({isFetching, allPosts}) => (
<div>
{/* access isFetching, allPosts directly */}
</div>
)
connect(
state => state.posts
)(Posts)
mapDispatchToProps
通常你需要写dispatch(anActionCreator())
使用bindActionCreators,你也可以更容易地做到这一点
connect(
state => state.posts,
dispatch => bindActionCreators({fetchPosts, deletePost}, dispatch)
)(Posts)
现在你可以在组件中使用它了
const Posts = ({isFetching, allPosts, fetchPosts, deletePost }) => (
<div>
<button onClick={() => fetchPosts()} />Fetch posts</button>
{/* access isFetching, allPosts directly */}
</div>
)
更新actionCreators..
一个actionCreator的例子:deletePost
const deletePostAction = (id) => ({
action: 'DELETE_POST',
payload: { id },
})
bindactioncreator会接受你的动作,把它们包装到分派调用中。(我没有阅读redux的源代码,但实现可能是这样的:
const bindActionCreators = (actions, dispatch) => {
return Object.keys(actions).reduce(actionsMap, actionNameInProps => {
actionsMap[actionNameInProps] = (...args) => dispatch(actions[actionNameInProps].call(null, ...args))
return actionsMap;
}, {})
}
其他回答
React-Redux连接用于更新每个操作的存储。
import { connect } from 'react-redux';
const AppContainer = connect(
mapStateToProps,
mapDispatchToProps
)(App);
export default AppContainer;
这篇博客里解释得非常简单明了。
你可以克隆github项目或复制粘贴从博客的代码来理解Redux连接。
It's a simple concept. Redux creates a ubiquitous state object (a store) from the actions in the reducers. Like a React component, this state doesn't have to be explicitly coded anywhere, but it helps developers to see a default state object in the reducer file to visualise what is happening. You import the reducer in the component to access the file. Then mapStateToProps selects only the key/value pairs in the store that its component needs. Think of it like Redux creating a global version of a React component's
this.state = ({
cats = [],
dogs = []
})
不可能通过使用mapStateToProps()来改变状态的结构。您所做的只是选择组件需要的存储键/值对,并将值(从存储中的键/值列表中)传递给组件中的道具(本地键)。在列表中,每次只执行一个值。在此过程中不会发生结构更改。
附注:商店是本地的。reducer通常也将状态传递给数据库,与Action creator一起混合,但首先要理解这个简单的概念。
P.P.S.将每个减速器分离到单独的文件中,并且只导入组件需要的减速器,这是一个很好的做法。
问:这样可以吗? 是的
问:这是预期的吗? 是的,这是预期的(如果您正在使用react-redux)。
问:这是反模式吗? 答:不,这不是反模式。
这被称为“连接”组件或“使其智能”。这是设计出来的。
它允许您在额外的时间内将组件与状态解耦,从而增加代码的模块化。它还允许您将组件状态简化为应用程序状态的子集,这实际上有助于您遵守Redux模式。
可以这样考虑:存储应该包含应用程序的整个状态。 对于大型应用程序,这可能包含数十个嵌套在多层深处的属性。 你不希望每次通话都带着这些东西(很贵)。
如果没有mapStateToProps或类似的东西,您可能会倾向于以另一种方式分割状态以提高性能/简化。
import React from 'react';
import {connect} from 'react-redux';
import Userlist from './Userlist';
class Userdetails extends React.Component{
render(){
return(
<div>
<p>Name : <span>{this.props.user.name}</span></p>
<p>ID : <span>{this.props.user.id}</span></p>
<p>Working : <span>{this.props.user.Working}</span></p>
<p>Age : <span>{this.props.user.age}</span></p>
</div>
);
}
}
function mapStateToProps(state){
return {
user:state.activeUser
}
}
export default connect(mapStateToProps, null)(Userdetails);
是的,你可以做到。您甚至还可以处理状态并返回对象。
function mapStateToProps(state){
let completed = someFunction (state);
return {
completed : completed,
}
}
如果您想将与状态相关的逻辑从呈现函数转移到它的外部,这将非常有用。