I have a component here with some variables inside this.state:
class Landing extends Component {
constructor(props) {
super(props);
this.state = {
searchQuery: "",
searchQueryWords: [],
};
}
//The rest of the component's rendering left out
searchQuery and searchQueryWords both get populated within this Landing component.
I have another component that is not a child to this one and I’d want to use those two populated variables for something else. This landing page comes before the other page on the website so there is no way to reach my other component without those variables having been established. Is there a way to do so, to send variables from one component to another like this?
If there does need to be a parent/child relationship to share these variables, how do I do so?
2
Answers
You can use ContextAPI for solve this problem
As it seems that you are using class based components I will be sharing two links
This will cover ContextAPI for class based components
https://legacy.reactjs.org/docs/context.html
If you have the possibility of using hooks to consume the context give it a try (Hooks can’t be used in class based components)
https://www.digitalocean.com/community/tutorials/react-usecontext
The main idea of Context API is that you create a Provider (that will have your state)
And you will have a consumer in this case the components that needs that state
The structure is more or less like this
modify the state if you want) it needs to be the parent of the
children in component tree) children doesn’t have to be direct
children (here is the magic)
through an API (useContext if using hooks or Context.Consumer
component) check the links that I shared with you
So no matter where are the children you will have access to that info
Hope this answer helps you to find the right solution to your problem
I agree with the commenter Dave Newton that you could lift the state up, but disagree with him that it doesn’t sound like you should. If you’re using Context at any level (including State Management like Redux), that’s really what’s going on–there’s just a level of obfuscation going on so that any interim levels of component between the higher level that knows about the persisted data and the lower level where it’s used aren’t aware of the data or responsible for passing it. However, this also creates a situation where it’s not clear how that data is getting to its destination and creates coupling to the exact mechanism for retrieving that data, so I’m not a fan.
If you’re going to raise state up, your component that is capturing the data now becomes just a dumb view that uses a callback to send the data it’s capturing further up the component tree to a common ancestor of the two components. Then it will receive that data back as props and just display it (so it will act as a managed component). Now the ancestor component will have the value and can pass it into the other component that needs it as props.
Next, you can manually wire it up on Context. The problem with this is each Context can only hold a single value, so if you make a general policy of this, you will wind up with a rat’s nest of Providers. Usually, that single value will contain two properties, one that is the value and the other that is a setter for the value. So you again have a callback and a value, only instead of getting these through props you have to glom onto a specific Context. For anyone familiar with the Service Locator pattern and why it came to be hated, this will feel icky, and rightfully so.
You can also use a dedicated state management library such as Redux. This might be the best solution if you expect to have lots of different state that you need to keep track of as the app grows. This again works basically the same way–you’ll get a callback that notionally will let you set the state from your component and there will be a related way to retrieve the specific piece of state you care about. The difference is you’re not directly changing the state in that callback, so in the layer where you do the actual change (in Redux it’s called a reducer), you have flexibility to combine the requested change with other things you know about the state or to make additional changes based on the incoming value (e.g. change other parts of the state).
Additionally, you could choose to store the values entered on the landing page in the URL, either as route parameters or as part of a query string.