Search code examples
reactjsreact-hooksuse-state

Use same useState in different components


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 ?


Solution

  • 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>
            </>
        )
    }