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的redux

Redux零碎知识点回顾

React Router / Redux应用程序中的数据/模型管理

在页面重新加载之间直接访问 redux 存储以访问和保持状态是一种不好的做法吗

Redux状态更新后没有调用ComponentDidMount?

在 Redux 中处理数据传递的正确方法是啥