1

I have a context provider file with the code as below

contexts.tsx

import React from "react";

export const Ordering = React.createContext({
  ordering: false,
});

export const Ordering2 = React.createContext({
  ordering2: true,
});

Since I may have many more contexts, I want to combine/Compose them.

Based on the this question Too many React Context providers the code context combiner is as below

combineComponents.tsx

import React from "react";

interface Props {
  components: Array<React.JSXElementConstructor<React.PropsWithChildren<any>>>;
  children: React.ReactNode;
}

export const Compose = (props: Props) => {
  const { components = [], children, ...rest } = props;

  return (
    <>
      {components.reduceRight((acc, Comp) => {
        return <Comp {...rest}>{acc}</Comp>;
      }, children)}
    </>
  );
};

As mentioned in the solution in the question, I am trying to use this in the App as below but I get the error as shown in the picture

App.tsx

export const App = () => {

    return (
      <Compose components={[Ordering, Ordering2]}>
        <div className="app">
          <EateryInfo orderStatus={Ordering} />
          <MenuButton orderStatus2={Ordering2} />
        </div>
      </Compose>
    );
}

enter image description here

If I do not use the combiner, I use the context providers as below & it works just fine.

Can you please guide me on what is wrong. Thanks.

export const App = () => {

    const [ordering, setOrdering] = useState(false);
   const [ordering2, setOrdering2] = useState(false);
    
  const handleOrdering = () => {
    setOrdering((s) => !s);
    };
    
    const handleOrdering2 = () => {
      setOrdering2((s) => !s);
    };

    return (
        <Ordering.Provider value={{ ordering: ordering }}>
            <Ordering2.Provider value={{ ordering2: ordering2 }}></Ordering2.Provider>
        <div className="app">
          <EateryInfo orderStatus={Ordering} />
          <MenuButton orderStatus2={Ordering2} />
        </div>
      </Ordering.Provider>
    );
}

1 Answer 1

1

As you see in your last example: the context objects are not the provider components. They contain them on the .Provider property. Compose wants an array of components, so pass those:

<Compose components={[Ordering.Provider, Ordering2.Provider]}>

I also haven't seen the React.JSXElementConstructor type before, and I'd expect components to be typed as React.ComponentType; but maybe either works.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. Your answer works. I stumbled on something similar here -> felixgerschau.com/react-typescript-context . One question though. I need to pass the value attribute when using the provider, how do I do that within components? I tried <Compose components={[<Ordering.Provider value={{ ordering: ordering }}>, <Ordering2.Provider value={{ ordering: ordering }}>]}> and it does now work
You won't be able to do that in your current implementation. I would modify Compose's components prop to accept something like [{component: Ordering.Provider, value: orderingValue}, ...]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.