Redux,如果我想访问数据,是否必须在所有容器中导入 store?

IT技术 reactjs redux
2021-03-27 23:07:58

也许我并没有将我的头放在 redux 上,但是我看到的所有示例都没有真正在容器之间访问太多状态,所以我没有看到 store.getState() 的太多用法,但即使你想派送,您需要访问商店,对吗?

因此,除了从“路径/到/商店/商店”导入导入商店

在我想要 getState() 或“调度”的每个文件中,我如何访问该状态,因为如果我不包含它,则存储未定义。

3个回答

通常,您只想制作可以访问 store 的顶级容器组件 - 它们会将任何必要的数据或动作分派作为props传递给它们的子组件。这是“智能”和“哑”组件之间的区别——“智能”组件知道 Redux 存储/状态,而“哑”组件只是将 props 传递给它们,而对更大的应用程序状态一无所知。

然而,即使只是将 store 传递给容器组件也会变得乏味。这就是 React-Redux 提供一个开箱即用的组件来包装整个应用程序的原因。在文档中查看这是Provider组件,当您用它包装整个应用程序时,您只需将 store 传递给组件一次

import createStore from '../store';

const store = createStore()

class App extends Component {

  render() {
    return (
      <Provider store={store}>
        <MainAppContainer />
      </Provider>
    )
  }
}

正如你在这里看到的,我有一个单独的配置文件,只用于我的商店,因为你可以做很多修改,对于任何远程复杂的应用程序,你会发现自己对使用compose应用中间件等事情做同样的事情

然后,您剩余的任何“智能”组件(通常是包装器)都需要监听 store。这是使用连接方法完成的这允许您将状态的各个部分映射到您的组件属性,以及将操作作为属性进行调度。

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.somethingChildComponent1,它可以访问something存储中数据,但它无权访问getSomething调度操作。同样,ChildComponent2只能访问getSomething调度操作,而不能访问something数据。这意味着您只将组件暴露给他们从商店需要的东西。

例如,因为ChildComponent2被传递给 dispatch action as getSomething,在 myonClick我可以调用this.props.getSomething并且它将调用 dispatch action而不需要任何对 store 的访问以同样的方式,它可以继续向下传递getSomething给另一个子组件,该组件可以调用它和/或向下传递它,并且循环可以无限期地继续。

class ChildComponent2 extends Component {

    render() {
        return (
            <div>
                <div onClick={this.props.getSomething}>Click me</div>
                <NestedComponent getSomething={this.props.getSomething} />
            </div>
        )
    }
}

从评论中编辑

虽然这与问题没有直接关系,但在评论中,您似乎对行动有些困惑。我实际上并没有在getSomething这里定义动作相反,在 Redux 应用程序中通常将所有操作定义放在一个名为actionCreators.js. 这包含与您的操作命名相同的函数,并返回一个带有type属性和操作所需的任何其他方法/数据的对象例如,这是一个非常简单的示例actionCreators.js文件:

export function getSomething() {
    return {
        type: 'GET_SOMETHING',
        payload: {
            something: 'Here is some data'
        }
    }
}

此操作类型是您的减速器将侦听以了解正在触发哪个操作的类型。

好的,我添加了那些导入语句,并在底部添加了一些更深入地解释操作的内容。希望有帮助。
2021-05-25 23:07:58
兄弟,你要杀了我!大声笑.. 你帮了很大的忙,谢谢!但是我有点(并且我已经阅读了文档),在理解函数“this.props.getSomething”如何获取 actionType 方面存在偏差 - 你不会传入它吗?我假设您没有使用 dispatch 因为我们绑定了它。再次感谢,如果这太过分了,我完全理解。不用担心。
2021-06-01 23:07:58
谢谢!!现在,如果您在 MainAppContainer 下有一个子组件怎么办,比如说“childAppContainer”,您能否展示一个示例,然后它将如何处理状态和调度动作?所以,如果你想在 ChildComponent2 中“更新”状态,你会说类似“getSomething.AddSomething.dispatch(SOME_CONST_ACTION_NAME);
2021-06-06 23:07:58
getSomething() 不能调用 getState() 吗?当需要获取商店的value时
2021-06-09 23:07:58
不用担心,伙计。我没有设置动作类型,getSomething甚至没有定义它,因为通常人们在一个名为actionCreators.js. 这将是一个只填充了函数的文件,这些函数返回一个带有type属性的对象以及该操作所需的任何其他内容。所以在那个组件上,我实际上需要从 'getSomething' 函数actionCreators.js以及bindActionCreatorsredux. 我省略了那些导入语句以稍微清理代码,但我可以将它们重新添加进去。
2021-06-19 23:07:58

如果你使用这个react-redux包,你最终会Provider用一个storeprop将你的组件包裹在 a 中这会在 React 上下文中设置您的单个存储,然后可以从connect子组件中方法访问它connect方法采用两个函数(mapStateToProps 和 mapDispatchToProps),它们是用于从存储中获取状态和分派消息的钩子。

看这里了解更多信息

@user798719 您仍然可以访问存储,而不是使用 mapStateToProps() 和 mapDispatchToProps(),但是您会将组件与 redux 紧密耦合。
2021-06-01 23:07:58
@user798719 您可以创建一个 HOC 并包装需要连接到商店的任何组件。例如:导出默认的connectorWrapper(MyComponent),connectorWrapper 是包含mapStateToProps 和mapDispatchToProps 的HOC 并返回connect(mapStateToProps, mapDispatchToProps)(WrappedComponent),如果需要一些代码,请告诉我,希望对您有所帮助。
2021-06-03 23:07:58
@Teomanshipahi - 我认为让每个组件直接与状态(redux)对话比无休止地将道具从组件传递到子组件要好,谁知道有多深......这是一件非常丑陋的事情。
2021-06-20 23:07:58
所以如果你有 10 个容器组件,每个容器组件都需要有自己的 connect() 实现,mapStateToProps() 和 mapDispatchToProps()?这如何节省任何打字和时间?我认为每个容器组件都可以直接访问商店。原型用例将是一个 User 对象,几乎每个子组件和孙组件都需要在任何地方访问它。孩子们如何轻松访问商店内的 User 对象?
2021-06-21 23:07:58

使用 mapStateToProps React 组件:

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;

动作(动作/index.js)

      // console.log('hahahahah')
      return {
        type: 'ADD_PRODUCT',
        payload: n
      }
    }