I have a main app and two components. It looks something like this:
MainApp:
const MainApp = () => {
return (
<>
<Component1 />
<Component2 />
</>
);
};
Component1:
const Component1 = () => {
const [state, setState] = useState(false)
return (
<>
<button type="button" onClick={() => setState(state => !state)}>Toggle</button>
</>
);
};
Component2:
type Props = {
state?: boolean;
};
const Component2 = ({ state }: Props) => {
return (
<>
{state ? <p>Hello</p> : <p>Not hello</p>}
</>
);
};
Right now it obviously doesn't work since Component2
doesn't get the state
from anywhere.
My problem is, how do I share the state between the two components, with the MainApp
being the intermediary ? Do I create the useState
variable in the MainApp
instead of Component1
, and then pass the state
and setState
to the toggle component (Component1)
, and pass the state to Component2
, or is there a better way to do this ?
CodePudding user response:
You should use contextApi
to handle this. I have shared a sample code which helps you understand more about context api.
Context api helps you share the states and functions of a component with other components inside the particular project.
In Filecontext.jsx
you can see createContext
which helps you in creating a context.
In App.jsx
, we have created the states and functions which has to be shared among the components and wrapped the components which can access the datas with that context by importing it.
In Formcomponent.jsx
, I am using useContext
to use the states and functions created in the App.jsx
.
Filecontext.jsx
import { createContext } from 'react'
export const Filecontext = createContext({});
App.jsx
import { Filecontext } from './Contexts/Filecontext';
import { useState } from 'react'
function App() {
const [name, setName] = useState("")
const [email, setEmail] = useState("")
const [mobileno, setMobileno] = useState("")
const showAlert = () => {
alert(`Hello ${name}`);
}
return (
<div className="App">
<Filecontext.Provider value={{ name, setName, email, setEmail, mobileno, setMobileno, showAlert }}>
<Formcomponent />
<Listcomponent />
</Filecontext.Provider>
</div>
);
}
export default App;
Formcomponent.jsx
import { Filecontext } from '../Contexts/Filecontext';
import { useContext } from 'react'
export default function Formcomponent() {
const { setName, setEmail, setMobileno, showAlert } = useContext(Filecontext)
return (
<>
<div className="form-group">
<label>Name : </label>
<input type="text" onChange={(e) => { setName(e.target.value) }} />
</div>
<div className="form-group">
<label>Email : </label>
<input type="email" onChange={(e) => { setEmail(e.target.value) }} />
</div>
<div className="form-group">
<label>Mobile No : </label>
<input type="number" onChange={(e) => { setMobileno(e.target.value) }} />
</div>
<div className="form-group">
<input type="submit" value="submit" onClick={() => { showAlert() }} />
</div>
</>
)
}
CodePudding user response:
If you don't want to use useContext()
or redux you would need to create the state in the MainApp
and then pass it to Component1
and Component2
.
// MainApp
const MainApp = () => {
const [state, setState] = useState(false)
return (
<>
<Component1 setState={setState} />
<Component2 state={state} />
</>
);
};
// Component1
type Component1Props = {
setState: React.Dispatch<React.SetStateAction<boolean>;
}
const Component1 = ({ setState } : Component1Props) => {
return (
<>
<button type="button" onClick={() => setState((prev) => !prev)}>Toggle</button>
</>
);
};
// Component2
type Component2Props = {
state?: boolean;
};
const Component2 = ({ state }: Component2Props) => {
return (
<>
{state ? <p>Hello</p> : <p>Not hello</p>}
</>
);
};
CodePudding user response:
You can use useContext hook to share same data in your components.
https://reactjs.org/docs/hooks-reference.html#usecontext or tools like redux.
Your question is a good question but it doesn't get solved with one line of code.
I mean above sources are for general state management. If you have a really small app and you don't need to update state from different components etc. then you can just provide the data from parent of component 1 and 2
const MainApp = () => {
const [stateData,setStateData] = useState();
return (
<>
<Component1 data={stateData}/>
<Component2 data={stateData} />
</>
);
};
then access to that data in your components with props
const Component1 = (props) => {
const dataFromParent = props.data
const [stateData,setStateData] = useState(dataFromParent);
return (
<>
<button type="button" onClick={() => setState(state => !state)}>Toggle</button>
</>
);
};