There are multiple ways to share data between components. You can use one of the following options:
If the component to which you want to pass the data is a child of
SearchFormcomponent, then you can pass it as aprop.If you are managing state via redux, you can connect components to the redux store and get the required data from the redux store in your components.
You can also use React's
Context APIto share common data between components that may or may not have a parent-child relationship.If the component that needs the data from
SearchFormcomponent, is a parent component ofSearchFormcomponent, you can pass a callback function to theSearchFormcomponent as apropand when data is available inSearchFormcomponent, call the callback function, received as aprop, and pass the data as an argument to that callback function.
Sharing data between React components - javascript
Sharing data between components in React
The most challenging thing for me about React is sharing state variables between components.
reactjs - How can I pass data between two React components, but the two components have no parent-child relationship? - Stack Overflow
What is React Context?
When should I use React Context?
Can React Context replace state management libraries like Redux?
Videos
There are multiple ways to share data between components. You can use one of the following options:
If the component to which you want to pass the data is a child of
SearchFormcomponent, then you can pass it as aprop.If you are managing state via redux, you can connect components to the redux store and get the required data from the redux store in your components.
You can also use React's
Context APIto share common data between components that may or may not have a parent-child relationship.If the component that needs the data from
SearchFormcomponent, is a parent component ofSearchFormcomponent, you can pass a callback function to theSearchFormcomponent as apropand when data is available inSearchFormcomponent, call the callback function, received as aprop, and pass the data as an argument to that callback function.
Ciao, when I want to share data between components I use React-Redux. Lets make an example: Suppose that you want to share data received by server (nameservers). At first install react-redux:
npm install react-redux
npm install redux
npm install @reduxjs/toolkit
Now we have to create the reducer and the action:
Lets say you have your component in a folder called "/components/MyComponent". Create a file called MyReducer.js.
/components/MyComponent/MyReducer.js
import { createReducer } from '@reduxjs/toolkit';
const initialState = {
nameservers: undefined,
};
const LoginReducer = createReducer(initialState, {
["SET_NAMESERVERS"]: (state, action) => {
state.nameservers= action.payload.nameservers;
},
})
export default MyReducer;
Now, on the same folder, createa file called MyAction.js
/components/MyComponent/MyAction.js
export const setNameServers = data => ({
type: "SET_NAMESERVERS",
payload: { nameservers: data }
});
Then create the store:
On your project root create a folder callled redux. Inside this create a folder called store. Then on this folder create a file called index.js.
redux/store/index.js
import { createStore, combineReducers } from "redux";
import MyReducer from '../../components/MyComponent/MyReducer';
const reducers = combineReducers({
MyReducer,
});
const store = createStore(reducers);
export default store;
Now on index.js file on root folder lets pass the store already created:
index.js
...
import { Provider } from 'react-redux';
import store from "./redux/store";
ReactDOM.render((
<Provider store={store}>
<App />
</Provider>
), document.getElementById('root') || document.createElement('div'));
We have almost done. On your component (MyComponent) you retrieve data from server. Once you have data, lets dispatch data to share into the store:
/components/MyComponent/MyComponent.js
...
import { useDispatch } from 'react-redux';
import { setNameServers } from './MyComponentAction';
const MyComponent: React.FC = () => {
const [nameservers, setNameservers] = useState([]);
const dispatch = useDispatch();
....
const handleSubmit = (event: any) => {
...
fetch(`https://dns.google.com/resolve?name=${domain}&type=NS`)
.then(results => results.json())
.then(data => {
setLoading(false);
if (data && data.Answer) {
data.Answer.sort((a: any, b: any) => a.data.localeCompare(b.data));
setNameservers(data.Answer);
dispatch(setNameServers(data.Answer)); // here the magic
}
});
};
};
Done! now you have nameservers on your react redux store and you can easly get it from another component like this:
OtherComponent.js
import { useSelector } from 'react-redux';
const OtherComponent: React.FC = () => {
const nameservers = useSelector(state => state.MyReducer.nameservers);
};
And if you log nameservers somewhere in OtherComponent you will see data retrieved in MyComponent. Awesome!
You can use any publish/subscribe events library and then make your components listen to any event you need.
For example:
import React from 'react'
import 'events' from 'eventPublishSubscribeLibrary'
class Component2 extends React.Component {
constructor (props) {
super(props)
this.toggleVisibility = this.toogleVisibility.bind(this)
this.state = {
visible = true
}
}
componentDidMount () {
events.subscribe('clicked-button', this.toogleVisibility)
}
toogleVisibility () {
this.setState({
visible: !this.state.visible
})
}
render () {
return visible && (
<div>content</div>
)
}
}
const Component4 = () => (
<button onClick={events.publish('clicked-button')}>Toggle Visibility</button>
)
You can find in this post by davidwalsh a simple implementation for a Pub/Sub JavaScript Object. Or you can search in npm for some other library.
the "right" way
This is the most simple implementation I can think of and for small projects it is a quick an easy solution that should work.
Anyway, as far as the project will grow a bit you will start to have a lot of actions/reactions between your components. With every new component you'll add it'll get more complicated to track all of these relations between all your components. Here is where it comes handy to have the global state of your application stored in one single place, and that is one of the three principles that redux is based on: the single source of truth.
I think it's perfect time for you to introduce some state to your app. Try Redux, it's awesome.
I'm new to React/Typescript with a Java/Python background. Maybe I am misunderstanding how to do this (or perhaps its some sort of anti-pattern..) but is it really hard to share state variables between components? What if I have an inputbutton component that acts as a setter for a state variable and another component that relies on the output of setter?
It seems quite complicated too create a parent component and propagate the props through that...
Use Redux by maintaining the states of all child components that you might need in a global store and obtain the data from said store.
https://react-redux.js.org/introduction/getting-started
make sure to use redux toolkit to simplify your setup: https://redux-toolkit.js.org/introduction/getting-started
I know two solutions to this.
The first and preferred one is to pass a exported function of one component as a property to the other component and thus linking them together, like:
import Dispay from './components/Dispay.js'
import Input from './views/Input.js'
<Input pushData={Dispay.pullData}/>
<Dispay/>
Here a working example of this:
https://codesandbox.io/s/pass-data-between-unrelated-components-rr2li?file=/src/App.js
The second method is an easy, although a bit dirty solution.
Use the browsers window object, as all React components can access this object.
In practice this might look like this:
Syncronous (event based):
components/MainComponent.js:
// call the other component's method with some data
window.processData("myDataString")
views/Element.js:
window.processData = function(data) {
// do something with your data like
console.log("MainComponent received data:",data);
}
Asyncronously
//read and write to this object from wherever you like
window.data