Redux,如果我想访问数据,是不是必须在所有容器中导入存储?
Posted
技术标签:
【中文标题】Redux,如果我想访问数据,是不是必须在所有容器中导入存储?【英文标题】:Redux, Do I have to import store in all my containers if I want to have access to the data?Redux,如果我想访问数据,是否必须在所有容器中导入存储? 【发布时间】:2016-05-19 22:22:25 【问题描述】:也许我并没有完全理解 redux,但我看到的所有示例并没有真正访问容器之间的状态太多,所以我没有看到 store.getState() 的太多用法,但即使你想派送,你需要访问商店,对吧?
所以,除了导入 从“路径/到/存储/存储”导入存储
在我想要 getState() 或“dispatch”的每个文件中,我如何访问该状态,因为如果我不包含它,则 store 是未定义的。
【问题讨论】:
【参考方案1】:一般来说,您只想制作可以访问商店的***容器组件 - 它们会将任何必要的数据或操作调度作为道具传递给它们的子组件。这是“智能”和“哑”组件之间的区别——“智能”组件知道 Redux 存储/状态,而“哑”组件只是将 props 传递给它们,不知道更大的应用程序状态。
但是,即使只是将 store 传递给容器组件也可能变得乏味。这就是为什么 React-Redux 提供了一个开箱即用的组件来包装整个应用程序。 Check it out 在文档中。这是Provider
组件,当您用它包装整个应用程序时,您只需将商店传递给组件一次:
import createStore from '../store';
const store = createStore()
class App extends Component
render()
return (
<Provider store=store>
<MainAppContainer />
</Provider>
)
正如您在此处看到的,我有一个单独的配置文件仅用于我的商店,因为您可以进行大量修改,并且对于任何远程复杂的应用程序,您会发现自己在使用 @987654322 之类的事情上做同样的事情@ 应用中间件。
那么您剩余的任何“智能”组件(通常是包装器)都需要监听存储。这是使用connect 方法完成的。这允许您将状态片段映射到组件属性以及将操作作为属性进行调度。
import bindActionCreators from 'redux';
import connect from 'react-redux';
import * as actionCreators from './actionCreators';
const mapStateToProps = function(state)
return
something: state.something,
const mapDispatchToProps = function (dispatch)
return bindActionCreators(
getSomething: actionCreators.getSomething,
, dispatch)
class MainAppContainer extends Component
componentDidMount()
//now has access to data like this.props.something, which is from store
//now has access to dispatch actions like this.props.getSomething
render()
//will pass down store data and dispatch actions to child components
return (
<div>
<ChildComponent1 something=this.props.something />
<ChildComponent2 getSomething=this.props.getSomething />
</div>
)
export default connect(mapStateToProps, mapDispatchToProps)(MainAppContainer)
因为您总是将调度操作和数据作为属性传递给您的子组件,所以您只需使用 this.props
引用该组件上的那些。
根据上面的示例,您会看到因为我将this.props.something
传递给ChildComponent1
,它可以访问来自商店的something
数据,但它无权访问getSomething
调度操作.同样,ChildComponent2
只能访问 getSomething
调度操作,但不能访问 something
数据。这意味着您只需将组件暴露给他们需要的商店。
例如,因为ChildComponent2
被作为getSomething
传递给调度操作,所以在我的onClick
中,我可以调用this.props.getSomething
,它会调用调度操作无需访问商店。以同样的方式,它可以继续将getSomething
传递给另一个子组件,并且该组件可以调用它和/或传递它,并且循环可以无限期地继续。
class ChildComponent2 extends Component
render()
return (
<div>
<div onClick=this.props.getSomething>Click me</div>
<NestedComponent getSomething=this.props.getSomething />
</div>
)
从 cmets 编辑
虽然这与问题没有直接关系,但在 cmets 中,您似乎对操作有些困惑。我实际上并没有在这里定义动作getSomething
。相反,在 Redux 应用程序中,通常会将所有操作定义放在一个名为 actionCreators.js
的单独文件中。这包含与您的操作命名相同的函数,并返回一个具有type
属性的对象以及操作所需的任何其他方法/数据。例如,这是一个非常简单的示例actionCreators.js
文件:
export function getSomething()
return
type: 'GET_SOMETHING',
payload:
something: 'Here is some data'
这个动作类型是你的 reducer 会监听的,以知道哪个动作被触发了。
【讨论】:
谢谢!!现在,如果您在 MainAppContainer 下有一个子组件,比如说“childAppContainer”,您能否展示一个示例,然后它将如何处理状态和调度操作?所以,如果你想在 ChildComponent2 中“更新”状态,你会说“getSomething.AddSomething.dispatch(SOME_CONST_ACTION_NAME); 兄弟,你会杀了我的!大声笑..你帮助很大,谢谢!但是我有点(并且我已经阅读了文档),在理解函数“this.props.getSomething”如何获得一个 actionType 方面有点歪曲 - 你不会把它传递进去吗?我假设您没有使用调度,因为我们绑定了它。再次感谢,如果这太过分了,我完全理解。不用担心。 别担心,伙计。我没有在getSomething
上设置动作类型,甚至没有定义它,因为通常人们在一个名为actionCreators.js
的单独文件中为他们的应用程序定义所有动作。这将是一个仅包含函数的文件,这些函数返回具有type
属性的对象以及该操作所需的任何其他内容。所以在那个组件上,我实际上需要从actionCreators.js
导入'getSomething` 函数以及从redux
导入bindActionCreators
模块。我省略了那些导入语句以稍微清理代码,但我可以将它们重新添加。
好的,我添加了这些导入语句,并在底部更深入地解释了这些操作。希望对您有所帮助。
getSomething() 不能调用 getState() ?当需要获取商店的价值时【参考方案2】:
如果您使用react-redux
包,您最终将使用store
属性将组件包装在Provider
中。这会在 React 上下文中设置您的单个存储,然后从子组件中的 connect
方法访问它。 connect
方法采用两个函数(mapStateToProps 和 mapDispatchToProps),它们是用于从存储中获取状态和发送消息的钩子。
Take a look here for more information
【讨论】:
那么如果你有10个容器组件,每个容器组件都需要有自己的connect()实现,mapStateToProps()和mapDispatchToProps()?这如何节省任何打字和时间?我认为每个容器组件都可以直接访问商店。原型用例是一个用户对象,几乎每个子组件和孙子组件都需要在任何地方访问该对象。孩子们如何轻松访问商店内的 User 对象? @user798719 你仍然可以访问 store,而不是使用 mapStateToProps() 和 mapDispatchToProps(),但是你会将你的组件紧密耦合到 redux。 @Teomanshipahi - 我认为让每个组件直接与状态 (redux) 对话比必须无休止地从组件传递道具到子组件更好,谁知道有多深......丑陋的事情要做。 @user798719 你可以创建一个 HOC 并包装任何需要连接到存储的组件。示例:导出默认connectorWrapper(MyComponent),connectorWrapper是HOC,包含mapStateToProps和mapDispatchToProps并返回connect(mapStateToProps, mapDispatchToProps)(WrappedComponent),如果需要一些代码,请告诉我,希望对您有所帮助。【参考方案3】:使用 mapStateToProps 反应组件:
import Item from './Item.jsx';
import createStore from 'redux';
import getProduct, addProduct from '../../actions';
import connect from "react-redux";
class Bundles extends React.Component
constructor(props)
super(props);
render()
var productData = this.props.productData
return (
<div>
<span>
productData.map(item => (
<Item item=item key=item.id />
))
</span>
</div >
)
const mapStateToProps = (state) =>
// console.log(state.getProduct)
return
productData: state.getProduct,
;
;
export default connect(mapStateToProps)(Bundles);
产品缩减器
const productReducer = (state = data, action) =>
switch (action.type)
case "GET_PRODUCT":
console.log(state)
return state
default:
return state;
export default productReducer;
RootReducer(所有减速器组合)
import getProduct from './products';
import getReviews from './reviews';
import combineReducers from 'redux';
const allReducers = combineReducers(
cartReducer, getProduct, getReviews
)
export default allReducers;
动作(action/index.js)
// console.log('hahahahah')
return
type: 'ADD_PRODUCT',
payload: n
【讨论】:
以上是关于Redux,如果我想访问数据,是不是必须在所有容器中导入存储?的主要内容,如果未能解决你的问题,请参考以下文章
React Router / Redux应用程序中的数据/模型管理
在页面重新加载之间直接访问 redux 存储以访问和保持状态是一种不好的做法吗