Reputation: 3910
I have two Components of the same level (no owner-ownee relation). Suppose by clicking "C" in Component A, I set the temperature unit to "C", and clicking "F", I set the unit to "F". In Component B, I need to display the temperature, so I need to get the unit. But that information is in A. I wonder how I can access the state in Component A?
Follow up:
In another Component C, which is also parallel to A and B, I have a link to another page:
<div className="bottom_link">
<Link to={'weather-stations/eaB1rJytnpS5mZ2m'}>view detail</Link>
</div>
I also need to pass the unit info to that page. I wonder what is the recommended way to do this? Thanks.
Upvotes: 4
Views: 2744
Reputation: 296
The best way to do this now is with the useContext hook. Create a new file that can be called TemperatureContext.js. In there you will need the following:
import {createContext} from 'react'
export const Temperature = createContext(null);
//you can replace null with an initial condition
Then, in your app.js file import the file you made and create a useState value. Then, wrap both Component A and Component B in a provider tag:
import React, {useState} from 'react'
import{Temperature} from '.TemperatureContext.js'
function App(){
const [temperature, setTemperature] = useState();
return(
<Temperature.Provider value={{temperature, setTemperature}}>
<ComponentA>
<ComponentB
</Temperature.Provider>
)}
Then, in each of your components, you can import the temperature state by
import React, {useContext} from 'react';
import{Temperature} from '.TemperatureContext.js';
function ComponentA(){
const [temperature, setTemperature] = useContext(Temperature);
const tempChange(entry)=>{
...
setTemperature(entry)
}
return(
...
)
}
Now, by using the tempChange function in ComponentA, it will alter the state in everything that is wrapped within the Provider tags. Thankfully, react has advanced a long way since this question was posted.
Upvotes: 2
Reputation: 1059
Have all of your components, A, B and C, owned by component X and move the state there. Have a handler in component X that you pass into the children, and that handler will do a setState
on X.
An alternative is to use the Flux approach. Here you would use a store and have each component read from that shared store's state. The change from F to C and back would be done via an action creator and store handler.
The second approach is an extrapolation of the first: you are essentially 'lifting' the state up into the global scope with a store, whereas you are lifting it into X's scope by using X's state.
In general in React, you want your components to be as stateless as possible. Therefore I would recommend using the first approach. You can then lift the state higher if necessary (say X, Y and Z need to share the state) and A, B and C are left untouched.
Using props rather than state has the nice side effect of forcing you to think about the API of your components. Exactly what data does this component require to do its job? Then those requirements are passed as props.
If I were to give any single piece of advice to someone starting in React, it would simply to not use state whenever possible. Even when you think you need it, you can often remove it, so you should be trying as hard as possible to avoid state.
I'm working on an app with hundreds and hundreds of components, and I can barely think of a place where we use this.setState
Upvotes: 2