How to Make a Shared State Between Two React Components

How to make a shared state between two react components?

What you want is to implement some object that stores your state, that can be modified using callback functions. You can then pass these functions to your React components.

For instance, you could create a store:

function Store(initialState = {}) {
this.state = initialState;
}
Store.prototype.mergeState = function(partialState) {
Object.assign(this.state, partialState);
};

var myStore = new Store();

ReactDOM.render(
<FirstComponent mergeState={myStore.mergeState.bind(myStore)} />,
firstElement
);
ReactDOM.render(
<SecondComponent mergeState={myStore.mergeState.bind(myStore)} />,
secondElement
);

Now, both the FirstComponent and SecondComponent instances can call this.props.mergeState({ . . .}) to assign state to the same store.

I leave Store.prototype.getState as an exercise for the reader.

Note that you can always pass the store (myStore) itself to the components; it just feels less react-y to do so.

Here is some more documentation that might be of interest:

React Docs: "Communicate Between Components"

For communication between two components that don't have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
Flux pattern is one of the possible ways to arrange this.

How can we share a state variables between two React components on the same page?

In this case, if you have given a pascal case naming for the text input such as function TextInput(){...} , then react will consider this as a separate component even if this is defined in the same file. This is why the state variables of the App component are not within the scope of TextInput

You can mitigate this by following either of the following approcahes,

  • Make text input a normal function which returns the JSX
function textInput(){
// the state variable 'success' and 'setSuccess' will be normally accessible here
return(
<div>
<input type="text" />
<div>
)
}

//return for the 'App' component

return(
<>
{textInput()}
</>
)

  • Passing the state as props to the TextInput component

    If you follow this approach, then you can have the TextInput component in a separate file as well

//parent 'App' component

function App(){
const [success, setSuccess] = useState(false);

return(
<>
<TextInput success={success} setSuccess={setSuccess}></TextInput>
</>
)
}

function TextInput(props){
const {success, setSuccess} = props;

// In here you can refer success and setSuccess normally as you would even if this is in a separate file
}

How to share state between state between React sibling component functions?

I suppose the best answer is: it depends.

However, the most simple solution would be to hold the value in a parent component and pass it down to both child components through props.

If you want to skip few nesting levels, you could reach for React context or state management tools like redux but that is already a heavy tool. Hard to say what exactly is best in your case with context you shared so far.

Shared state between Parent and Child component

setCollectionIds(collectionIds.push(newId))  

Array.push is not returning the array but the length of the array

const array = [1]
console.log(array.push(2)) // prints 2 because array.length is 2

You are effectively setting state to a number, not array, you can do:

setCollectionIds([...collectionIds, newId])  

or

setCollectionIds(collectionIds.concat([newId]))  

Is it possible to share states between components using the useState() hook in React?

If you are referring to component state, then hooks will not help you share it between components. Component state is local to the component. If your state lives in context, then useContext hook would be helpful.

Fundamentally, I think you misunderstood the line "sharing stateful logic between components". Stateful logic is different from state. Stateful logic is stuff that you do that modifies state. For e.g., a component subscribing to a store in componentDidMount() and unsubscribing in componentWillUnmount(). This subscribing/unsubscribing behavior can be implemented in a hook and components which need this behavior can just use the hook.

If you want to share state between components, there are various ways to do so, each with its own merits:

1. Lift State Up

Lift state up to a common ancestor component of the two components.

function Ancestor() {
const [count, setCount] = useState(999);
return <>
<DescendantA count={count} onCountChange={setCount} />
<DescendantB count={count} onCountChange={setCount} />
</>;
}

This state sharing approach is not fundamentally different from the traditional way of using state, hooks just give us a different way to declare component state.

2. Context

If the descendants are too deep down in the component hierarchy and you don't want to pass the state down too many layers, you could use the Context API.

There's a useContext hook which you can leverage on within the child components.

3. External State Management Solution

State management libraries like Redux or Mobx. Your state will then live in a store outside of React and components can connect/subscribe to the store to receive updates.

Share state between components

I think you just need 'value' to accept a prop passed into it on the switch button. Then wherever you use switch button just pass a boolean value into it from state e.g.

<SwitchButton enabled={this.state.switchEnabled}/>

As for setting state 'globally' so this.state.switchEnabled can be updated from various places / accessible all over the app you need to look into state management tools like Redux (or I hear 'React Hooks' is now a thing and preferred....)



Related Topics



Leave a reply



Submit