React: How to combo multiple ContextProvider

Created on 2 Jan 2019  路  3Comments  路  Source: facebook/react

I learn the Hooks锛宨t's so good!
Bug when I use hooks: useReducer銆侷 confused by multiple provider.

my simple files

  1. app.js:

    import Provider from './store/index.js';
    
    ReactDOM.render(
    <Provider>
      <Router history={history}>
        <Layout>
          <Switch>
            <Route ... />
          </Switch>
        </Layout>
      </Router>
    </Provider>,
    CONTAINER
    );
    
  2. ./store/index.js

    import providerOne from './providerOne.js';
    import ProviderTwo from './providerTwo.js';
    import ProviderThree from './providerThree.js';
    // there maybe have many providers...
    
    return (
    <ProviderOne>
      <ProviderTwo>
        <ProviderThree>
          {props.children}
        </ProviderThree>
      </ProviderTwo>
    </ProviderOne>
    );
    
  3. ./store/providerOne.js

    const Context = React.createContext();
    
    const initState = [];
    const reducer = (state, action) => {
    switch (action.type) {
      case 'xxx':
        return xxx;
      default:
        return state;
    }
    };
    
    const ProviderOne = (props) => {
    const [state, dispatch] = React.useReducer(reducer, initState);
    
    return <Context.Provider value={{ state, dispatch }}>{props.children}</Context.Provider>;
    };
    
    export default ProviderOne;
    

my confusion

In file ./store/index.js, I must write many times <Provider> structure.
There is any way to solve it.

Support Redirect

Most helpful comment

Hey @hangyangws , I was just thinking about the same problem, and I've found the solution for this in this repo: https://github.com/FormidableLabs/react-context-composer

This solution was fine for me, hope it helps you too.

Simply put, if you want to get rid of the deep nesting of context providers you can write a util functional component like this:

export const ContextProviderComposer = ({contextProviders, children}) => {
  return contextProviders.reduceRight((children, parent, index) => React.cloneElement(parent, { children }), children);
};

ContextProviderComposer.propTypes = {
  contextProviders: PropTypes.arrayOf(
    PropTypes.element,
  ).isRequired,
  children: PropTypes.node.isRequired,
};

And you can use it in a component by listing your context providers:

import providerOne from './providerOne.js';
import ProviderTwo from './providerTwo.js';
import ProviderThree from './providerThree.js';

return (
  <ContextProviderComposer contextProviders={[
    <ProviderOne key={0}/>
    <ProviderTwo key={1}/>
    <ProviderThree key={2}/>
  ]}>
    { props.children }
  </ContextProviderComposer>
);

All 3 comments

Hey @hangyangws , I was just thinking about the same problem, and I've found the solution for this in this repo: https://github.com/FormidableLabs/react-context-composer

This solution was fine for me, hope it helps you too.

Simply put, if you want to get rid of the deep nesting of context providers you can write a util functional component like this:

export const ContextProviderComposer = ({contextProviders, children}) => {
  return contextProviders.reduceRight((children, parent, index) => React.cloneElement(parent, { children }), children);
};

ContextProviderComposer.propTypes = {
  contextProviders: PropTypes.arrayOf(
    PropTypes.element,
  ).isRequired,
  children: PropTypes.node.isRequired,
};

And you can use it in a component by listing your context providers:

import providerOne from './providerOne.js';
import ProviderTwo from './providerTwo.js';
import ProviderThree from './providerThree.js';

return (
  <ContextProviderComposer contextProviders={[
    <ProviderOne key={0}/>
    <ProviderTwo key={1}/>
    <ProviderThree key={2}/>
  ]}>
    { props.children }
  </ContextProviderComposer>
);

We use the issue tracker for bug reports and feature requests.

If you have a question, please check our community support resources:
https://facebook.github.io/react/community/support.html

I have created another state management library that is better at service composition. Here is a demo of avoiding provider hell. Feel free to try it or read its source(100 lines of code)!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zpao picture zpao  路  3Comments

jvorcak picture jvorcak  路  3Comments

trusktr picture trusktr  路  3Comments

UnbearableBear picture UnbearableBear  路  3Comments

jimfb picture jimfb  路  3Comments