Is it possible to share states between components using the useState() hook in React?
If you are referring to component state, then hooks will not help you share it between components. Component state is local to the component. If your state lives in context, then useContext
hook would be helpful.
Fundamentally, I think you misunderstood the line "sharing stateful logic between components". Stateful logic is different from state. Stateful logic is stuff that you do that modifies state. For e.g., a component subscribing to a store in componentDidMount()
and unsubscribing in componentWillUnmount()
. This subscribing/unsubscribing behavior can be implemented in a hook and components which need this behavior can just use the hook.
If you want to share state between components, there are various ways to do so, each with its own merits:
1. Lift State Up
Lift state up to a common ancestor component of the two components.function Ancestor() {
const [count, setCount] = useState(999);
return <>
<DescendantA count={count} onCountChange={setCount} />
<DescendantB count={count} onCountChange={setCount} />
</>;
}
This state sharing approach is not fundamentally different from the traditional way of using state, hooks just give us a different way to declare component state.2. Context
If the descendants are too deep down in the component hierarchy and you don't want to pass the state down too many layers, you could use the Context API.There's a useContext
hook which you can leverage on within the child components.
3. External State Management Solution
State management libraries like Redux or Mobx. Your state will then live in a store outside of React and components can connect/subscribe to the store to receive updates.How can I share state data between components using custom hooks?
You'll need to use Context, but it's not that bad..
create your context..
import React, { useState } from 'react';
export const FlashContext = React.createContext();
export const FlashProvider = ({ children }) => {
const [messages, setMessages] = useState([]);
return (
<FlashContext.Provider value={{ messages, setMessages }}>
{children}
</FlashContext.Provider>
);
};
wrap your components in the provider somewhere higher in the tree..import React from "react";
import { FlashProvider } from "./flash-context";
const App = () => <FlashProvider><TheRest /></FlashProvider>;
export default App;
then use the context in your custom hook..import React, { useContext } from "react";
import { FlashContext } from "./flash-context";
export default function useFlash() {
const { messages, setMessages } = useContext(FlashContext);
const showFlash = (message) => {
setMessages([...messages, message]);
};
const clearMessage = (index) => {
setMessages(messages.filter((_m, i) => index !== i));
};
return {
messages,
showFlash,
clearMessage
};
}
How to pass a value for useState hook from another component in ReactJS?
It seems like you want the Child
component to simply toggle the display
value of some content in the Parent
component.
As you've defined them though they are not parent-child, but rather they are siblings. As such if they need to share state/behavior, then the solution is to lift state up to a common ancestor, App
in this case.
<Route path="/content">
<Menu />
<div className="content-flexbox">
<Parent /> // <-- siblings
<Child /> // <-- siblings
</div>
<Footer />
</Route>
See: Lifting State UpMove the showHideContent
state and updater into the parent App
component, pass down the showHideContent
state to Parent
and the toggleVisibility
callback to the Child
.
function Parent({ showHideContent }) {
return <div style={{ display: showHideContent }}>Some content here...</div>;
}
function Child({ onClick }) {
return (
<button type="button" onClick={onClick}>
Show/Hide Content
</button>
);
}
export default function App() {
const [showHideContent, setShowHideContent] = React.useState("none");
const toggleVisibility = () =>
setShowHideContent((value) => (value === "none" ? "block" : "none"));
return (
...
<Route path="/content">
<Menu />
<div className="content-flexbox">
<Parent showHideContent={showHideContent} />
<Child onClick={toggleVisibility} />
</div>
<Footer />
</Route>
...
);
}
Use same useState in different components
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 componentIn
with other components inside the particular project.
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.jsximport { 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.jsximport { 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>
</>
)
}
React Hooks, how to share state between two functions
import React, { useState } from "react";
function Home() {
const [mobileNavOpen, setMobileNavOpen] = useState(false);
return (
<div>
<button
onClick={() => setMobileNavOpen(true)}
type="button"
className="btn"
>
X
</button>
{mobileNavOpen && <MobileNav setMobileNavOpen={setMobileNavOpen} />}
</div>
);
}
function MobileNav({setMobileNavOpen}) {
return (
<div>
<button
onClick={() => setMobileNavOpen(false)}
type="button"
className="btn"
>
X
</button>
</div>
);
}
export default Home;
- you have to move the useState hook to the component body
- pass down the state setter function to your child component
How to share useState in different components
To share state between components, the recommended way is to use Context (https://reactjs.org/docs/context.html)
In short, crete a js file with where you export a React.createContext()
export const LangContext = React.createContext()
Then wrap your application in provider<LangContext.Provider value={}>{children}</LangContext.Provider>
Then grab the state from the context by getting the context in the componentconst context = React.useContext(LangContext)
How to transfer state between React components with hooks?
Classes and functional components (or func-comp as my mate calls them) are the same in respect to props.
You can pass props from parent to child in a functional component just like how you'd do with a class.
//Parent
const Parent = () => {
const [state, setState] = React.useState({ products: 1, isAvailable: true})
const addProduct = (data) => {
// Your function
}
return (
<Child product info={state} addProduct={addProduct} />
)
}
export default Parent
And in the child component you can receive the props typically the way you would will classes.
const Child = ({productInfo, addProduct}) => {
// Do what ever you like with the props
}
Cheers! How to pass a state (hook) between separated files (components) in React
If state is shared between components, then you need to elevate that state to a common parent.
Then you can pass that state down to the children, probably as props or context.
For example:
function App() {
const [career, setCareer] = React.useState('');
return <>
<MenuPopupState career={career} onClick={setCareer} />
<Header career={career} />
</>
}
function MenuPopupState(props){
return (
<div>
<button onClick={() => props.onClick(props.career)}>
Press me
</button>
</div>
)
}
function Header(props){
return (
<div>
<a key={props.career.id}>
{props.career.name}
</a>
</div>
)
}
Related Topics
Object Doesn't Support This Property or Method Rails Windows 64Bit
Angularjs Communication Between Directives
What Is the JavaScript Mime Type for the Type Attribute of a Script Tag
Where Should I Initialize Pg-Promise
Invoke a Callback at the End of a Transition
How to Close a Window with JavaScript on Mozilla Firefox 3
Can Jquery Provide the Tag Name
What Are Some Empirical Technical Reasons Not to Use Jquery
Why Are Await and Async Valid Variable Names
Remove Whitespace and Line Breaks Between HTML Elements Using Jquery
Why a Variable Defined Global Is Undefined
How to Concatenate Regex Literals in JavaScript
Get Selected Value/Text from Select on Change
Why Threre Is No Way to Download File Using Ajax Request
Handling Key-Press Events (F1-F12) Using JavaScript and Jquery, Cross-Browser
Angular 2.1.0 Create Child Component on the Fly, Dynamically