3

I've got a React app of the form:

<App>
  <ParentComponent>
    <FormComponent>
    <AnotherComponent>
  </ParentComponent>
</App>

I want to be able to update some state values of <FormComponent> by clicking on elements in <AnotherComponent>.

I don't want to place them inside each other, but keep them side-by-side. I don't want to lift up <FormComponent> state as it's nicely encapsulated.

What's the best way to achieve this? Can I do it with just react or do I need RxJS/something else?

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
cjm2671
  • 18,348
  • 31
  • 102
  • 161
  • you can do it through `useContext` hook. if you are okay with third party library then you can use redux. which is preffered for complex state management – upog May 10 '20 at 15:53
  • They are already wrapped in a context that provides other stuff; how exactly would you use `useContext` in this case? – cjm2671 May 10 '20 at 15:57
  • `React.createContext` to create context and have to wrap conponent with `contex.provider`. i see Dennis have provided the code – upog May 10 '20 at 16:01

3 Answers3

4

The data in React Flows Down.

If you don't want to lift the state up, what's left is Context API or any state management library like Redux and MobX (both implement Context API with different strategy).

But still, the state is "above" FormComponent (you still lifting state up).

const Context = React.createContext();

const ParentComponent = () => {
  const contextState = useState(DEFAULT_STATE);
  return (
    <Context.Provider value={contextState}>
      <FormComponent />
      <AnotherComponent />
    </Context.Provider>
  );
};

const FormComponent = () => {
  const [, setState] = useContext(Context);
  // use setState
};

const AnotherComponent = () => {
  const [state] = useContext(Context);
  // valid state updated from FormComponent
};
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • This will re-render ParentComponent. Let's say we still want to get FormComponent and AnotherComponent to interact but without re-rendering ParentComponent? – Pierre Dec 15 '21 at 22:27
  • 1. Let it rerender - don't pre optimize. 2. You can't bailout context, see: https://stackoverflow.com/questions/64985555/how-to-solve-problem-with-too-many-re-renders-in-context/64985673#64985673 – Dennis Vash Dec 16 '21 at 08:25
0

As far as I can tell the "right thing" to do in these instances is move the state up one level, into your Parent component.

If you have a look at the Intro to React:

To collect data from multiple children, or to have two child components communicate with each other, you need to declare the shared state in their parent component instead.

"Lifting state up" is a common thing in React applications and doesn't require introducing a state management solution like Redux or RxJS.

wpp
  • 7,093
  • 4
  • 33
  • 65
  • Thing is, doing this will make a mess of my code, which is currently very neatly encapsulated in components. The only thing I want to do is set form values based on clicking somewhere outside the form component; moving state up to facilitate this is tantamount to a rewrite... – cjm2671 May 10 '20 at 16:04
0

Apart from the ways mentioned above you can pass down a function as prop from the Parent component to AnotherComponent. And when clicking any element in Another component, pass the intended value in that function, which will in turn be transferred to ParentComponent. And you can then pass the value as props to the FormComponent from the ParentComponent. You can check this example for better understanding https://react-m9skpu.stackblitz.io

Avik
  • 739
  • 9
  • 15