【问题标题】:how react-redux gets the store object of provider?react-redux如何获取provider的store对象?
【发布时间】:2020-08-07 21:49:39
【问题描述】:

这是一个基本的 react-redux 应用程序 (sandbox):

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { useDispatch, Provider, useSelector, useStore } from "react-redux";
const App = () => {
  const store = useStore(); // <- how it gets the store object of Provider ?
  const state = useSelector(s => s);
  return <div>{state}</div>;
};
ReactDOM.render(
  <Provider store={createStore((state, action) => 5)}>
    <App />
  </Provider>,
  document.getElementById("root")
);

现在我的问题是:

useStore 这样的钩子如何获取我们在&lt;Provider store={store}&gt; 中设置的 store 对象?

如果是dom,我们可以使用this.closest('.provider').getAttribute('store')来获取父元素中provider元素的store属性。但是我们如何在 react 中做到这一点呢?

我问它是因为我想了解 react-redux 是如何在幕后工作的。

谢谢。

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    react-redux 使用一个提供程序来保存它所使用的所有属性。它允许您通过诸如 hooks API (useStore, useDispatch) 或 connect() HOC API 等不错的 API 从提供程序中提取内部结构。

    为了帮助您以更简单的方式对其进行可视化,让我们使用 React Context API 编写一个“迷你”react-redux

    import React, { createContext, useContext } from 'react';
    
    const InternalProvider = createContext();
    
    /**
     * This is the `Provider` you import from `react-redux`.
     * It holds all of the things child components will need
     */
    const Provider = ({ store, children }) => {
      /**
       * This `context` object is what's going to be passed down 
       * through React Context API. You can use `<Consumer>` or 
       * `useContext` to get this object from any react-redux-internal
       * child component.  We'll consume it on our `useStore` and
       * `useDispatch` hooks
       */
      const context = {
        getStore: () => store,
        getDispatch: (action) => store.dispatch,
      };
    
      return (
        <InternalProvider value={context}>
          {children}
        </InternalProvider>
      );
    }
    
    
    /**
     * These are the hooks you import from `react-redux`.
     * It's dead simple, you use `useContext` to pull the `context`
     * object, and voila! you have a reference.
     */
    const useStore = () => {
      const context = useContext(InternalProvider)
      const store = context.getStore();
      return context;
    };
    
    const useDispatch = () => {
      const { getDispatch } useContext(InternalProvider);
    
      return getDispatch();
    };
    
    
    /***************************************
     * Your redux-aware components
     *
     * This is how you consume `react-redux` in your app
     */
    const MyComponent = () => {
      const store = useStore();
      const dispatch = useDispatch();
    
      return <>Foo</>
    }
    
    const App = () => (
      <Provider store={store}>
        <MyComponent />
      </Provider>
    )
    

    【讨论】:

    • 感谢您的回答。你有一个小的语法错误:它应该是:InternalProvider.Provider。我实现了一个基本的,它工作:codesandbox.io/s/my-stack-q-answer-hs01q 所以简而言之,它使用react context,而react context 让我们可以访问特定父级的值(使用createContextuseContext)。挺好的。感谢您的宝贵时间。
    猜你喜欢
    • 2020-02-16
    • 2018-02-13
    • 2016-06-22
    • 2021-07-23
    • 2018-06-18
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多