Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to combo multiple ContextProvider #14520

Closed
hangyangws opened this issue Jan 2, 2019 · 2 comments

Comments

@hangyangws
Copy link

commented Jan 2, 2019

I learn the Hooks,it's so good!
Bug when I use hooks: useReducer。I 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
);
  1. ./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>
);
  1. ./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.

@tmenyhart

This comment has been minimized.

Copy link

commented Jan 3, 2019

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>
);
@aweary

This comment has been minimized.

Copy link
Member

commented Jan 5, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.