pass setState from parent to its child component using React Hook - reactjs

How do I pass setState from parent to its child component using React Hooks? Code is provided:
App.js
export default App() {
<Main>
<Widget/>
</Main>
}
Main.js
export default Main() {
const [marketProducts, setMarketProducts] = useState([]);
...
return
<DataContext.Provider value={marketProducts}>
...
{props.children}
</DataContext.Provider>;
}
Widget.js
export default Widget() {
return <div>
<NavComponent/>
...
</div>
}
NavComponent.js
export default NavComponent() {
// need setMarketProducts here but not sure how to bring from Main.js to here
return <div>
...
</div>
}

You can pass the setMarketProducts to you DataContext the same way you passed the marketProducts. Export Datacontext form Main.js. Although I suggest to create seprate file for your context
export default Main(props) {
const [marketProducts, setMarketProducts] = useState([]);
...
return
<DataContext.Provider value={marketProducts, setMarketProducts}>
...
{props.children}
</DataContext.Provider>;
}
Then use useContext hook in NavComponent.js to access setMarketProducts
import { DataContext } from 'Main'
...
export default Widget() {
const { setMarketProducts } = React.useContext(DataContext)
return <div>
...
</div>
}

You can pass setMarketProducts down the chain as shown in example below. Other wise you can use some kind of store e.g. useContext or redux
export default App() {
const [marketProducts, setMarketProducts] = useState([]);
<Main setMarketProducts={setMarketProducts} marketProducts={marketProducts}>
<Widget setMarketProducts={setMarketProducts}/>
</Main>
}
export default Main({ setMarketProducts,marketProducts, ...props }) {
...
return
<DataContext.Provider value={marketProducts}>
...
{props.children}
</DataContext.Provider>;
}
export default Widget({ setMarketProducts }) {
return <div>
<NavComponent setMarketProducts={setMarketProducts}/>
...
</div>
}
export default NavComponent({ setMarketProducts }) {
// need setMarketProducts here but not sure how to bring from Main.js to here
return <div>
...
</div>
}

Related

Prevent update of all components on button click

I have an array of objects and displayed them using map. A '+' button associated with each component. I want to update the count of a specific component on button click. I tried with the following code. However, it is updating the count of all the other components also. What can I do to fix this?
import { useState } from 'react';
import { people } from './Data.js';
function App() {
const[count,setCount]=useState(0)
const updateCount=()=>{
setCount(count+1)
}
return (
<div>
<h4>List of Items</h4>
{
people.map((item)=>{
return (
<div key={item.id}>count:{count}
<button onClick={()=>updateCount}>+</button>
</div>
)
})
}
</div>
);
}
export default App;
You need to manage the state individually. Here's a possible alternative, hope it helps.
import React,{ useState } from 'react';
import { people } from './Data.js';
function PeopleItem(props) {
const[count,setCount]=useState(0)
const updateCount=()=>setCount(count+1)
const {item} = props
return <div>count:{count}
<button onClick={updateCount}>+</button>
</div>
}
export function App() {
return (
<div>
<h4>List of Items</h4>
{
people.map((item)=> <PeopleItem key={item.id} item={item}/>)
}
</div>
);
}
If you want to update count on a single component you need to initialize the useState inside the child component. Extract the map and create a component for the return statement. Consider the following:
import { useState } from 'react';
import { people } from './Data.js';
function ChildComponent(props){
const[count,setCount]=useState(0)
const updateCount=() => {
setCount(prev => prev + 1)
}
return (<div>
count:{count}
<button onClick={()=>updateCount()}>+</button>
</div>)
}
function App() {
return (
<div>
<h4>List of Items</h4>
{
people.map((item)=>{
return (
<ChildComponent key={item.id}/>
)
})
}
</div>
);
}
export default App;

How to access variable from parent component using JSX Namespacing in React

I want to pass variable from parent component to props.children
Is posible if I access parent variable to props.children like this?
function App() {
return (
<div>
<Example>
<Example.Title>
<p>this is Title</p>
</Example.Title>
<Example.Body>
<p>this is Body</p>
<p>value from {parent}</p>
</Example.Body>
</Example>
</div>
);
}
export default App;
Parent Component
import { useState } from "react";
function Example(props) {
const [parent, setParent] = useState("parent");
return <div>{props.children}</div>;
}
Example.Title = (props) => <>{props.children}</>;
Example.Body = (props) => <>{props.children}</>;
export default Example;
You can't do it like this, because Example.Body component is already rendered when passed from App to Example.
Example must pass the "parent" prop to Example.Body
One solution is to use children as a render props (see it working there):
export default function App() {
return (
<div>
<Example>
{(parentParam) => (
<>
<Title>
<p>this is Title</p>
</Title>
<Body>
<p>this is Body</p>
<p>value from {parentParam}</p>
</Body>
</>
)}
</Example>
</div>
);
}
function Example(props) {
const [parent, setParent] = useState('parent');
return <div>{props.children(parent)}</div>;
}

how can I call a method that is inside of Component? (I can't pass this method in props)

this seems like a duplicate question but it is not, the examples I have seen explain how to pass a function through props.
I have three components: ComponentA, ComponentB and App (App is the component root). I want to call a function contains in ComponentA using a button that is inside of ComponentB.
import "./styles.css";
import ComponentA from "./componentA";
import ComponentB from "./componentB";
export default function App() {
return (
<div className="App">
<>
<ComponentA>
<ComponentB />
</ComponentA>
</>
</div>
);
}
const ComponentA = ({ children }) => {
const hello = () => {
alert("hello");
//In my real scenario, this method contains a big logic...
};
return (
<>
Component A<div>{children}</div>
</>
);
};
const ComponentB = () => {
const callComponentAFunction = () => {
// I need call "hello()" from ComponentA
};
return (
<>
<button onClick={callComponentAFunction}>
Call function from ComponentA
</button>
</>
);
};
How can I call hello() (function inside of ComponentA) from ComponentB?
this is my live code
You can achieve that in many ways. Pass that function as props from component A.
Working example Modified code
//App.js
import "./styles.css";
import ComponentA from "./componentA";
// import ComponentB from "./componentB";
export default function App() {
return (
<div className="App">
<>
<ComponentA />
</>
</div>
);
}
//Component A
import ComponentB from "./componentB";
const ComponentA = ({ children }) => {
const hello = () => {
alert("hello");
};
return (
<>
Component A<div>{children}</div>
<ComponentB hello={hello} />
</>
);
};
export default ComponentA;
//Component B
const ComponentB = ({ hello }) => {
return (
<>
<button onClick={hello}>Call function from ComponentA</button>
</>
);
};
export default ComponentB;
you can also use the React.Children.map, the example like this: https://codesandbox.io/s/hardcore-ellis-ksgkd?file=/src/componentB.js

How to send functional data to another page in React

Playing.js File
import { useState } from "react";
function Playing(){
const [sidebar, setSidebar] = useState(false);
const sidebarFunc = () => {
sidebar ? setSidebar(false) : setSidebar(false);
}
return(
<i onClick={sidebarFunc}>Click</i>
);
}
export default Playing;
Sidebar.js File
function SideBar() {
return (
<div className="">Side Bar</div>
);
}
export default SideBar;
App.js File
import Sidebar from "./Sidebar.js";
import Playing from "./Playing.js";
function App(){
return(
<>
<Sidebar />
<Playing />
</>
);
}
I'm new to react, so try avoiding mistakes by my side. Here i'm trying a way in which the after clicking the Click text, the usestate variable sidebar gets triggered. But the sidebar couldn't be exported so as to get an outcome for Sidebar functional div as <div className="sidebar?"Show":"Hide">Side Bar</div>.
Is there a solution for the same or any other ways it can be done.
Thank you in advance
You can create a state in parent component and then use this state in child component by passing through props and a callback function
App.js File
import Sidebar from "./Sidebar.js";
import Playing from "./Playing.js";
function App(){
const [sidebar, setSidebar] = useState(false);
return(
<>
<Sidebar sidebar={sidebar}/>
<Playing sidebar={sidebar} setSidebar={setSidebar}/>
</>
);
}
Playing.js
import from "react";
function Playing({sidebar,setSidebar}){
const sidebarFunc = () => {
sidebar ? setSidebar(false) : setSidebar(false);
}
return(
<i onClick={sidebarFunc}>Click</i>
);
}
export default Playing;
SideBar.js
function SideBar({sidebar}) {
return (
<div className=`${sidebar?"Show":"Hide"}`>Side Bar</div>
);
}
export default SideBar;
Place the useState() declaration in App.js.
App.js
function App(){
const [sidebar, setSidebar] = useState(false);
return(
<>
<Sidebar sidebar={sidebar}/>
<Playing sidebar={sidebar} setSidebar={(bool) => setSidebar(bool)}/>
</>
);
}
SideBar.js
function SideBar(props) {
return (
<div className={props.sidebar ? "Show" : "Hide"}>Side Bar</div>
);
}
export default SideBar;
Playing.js
function Playing(props){
const sidebarFunc = () => {
props.sidebar ? props.setSidebar(false) : props.setSidebar(false);
}
return(
<i onClick={sidebarFunc()}>Click</i>
);
}
export default Playing;

Pass context between siblings using context in React

I have the following code where I am trying to get a value from one component to its sibling using the context api.
import React from "react";
import ReactDOM from "react-dom";
function App() {
return (
<div>
<TheButton />
<Display />
</div>
);
}
export const NumberContext = React.createContext();
function TheButton() {
return (
<NumberContext.Provider value={"test"}>
<button>Click me</button>
</NumberContext.Provider>
);
}
function Display() {
const context = React.useContext(NumberContext);
return <div>The answer {context}.</div>;
}
ReactDOM.render(<App />, document.querySelector("#root"));
As you can see I am passing the 'test' value in the provider, but when the page renders all I see is "The answer ."
Here is a a codesandbox for the issue https://codesandbox.io/s/pedantic-forest-zjlc2
Despite the fact that context gives you a decoupled way of passing props the Provider still must be on a higher hierarchy. Provide your context from your App and consume it from children.
export const NumberContext = React.createContext();
function App() {
const [foo, changeFoo] = useState('foo')
return (
<NumberContext.Provider value={{ foo, changeFoo }}>
<TheButton />
<Display />
</NumberContext.Provider>
);
}
function TheButton() {
const { changeFoo } = useContext(NumberContext)
return (
<button onClick={() => changeFoo('bar')}>Click me</button>
);
}
function Display() {
const context = React.useContext(NumberContext);
return <div>The answer {context.foo}.</div>;
}

Resources