In react functional component, stop child re-rendering when parent function is called from child component - reactjs

in react I have 2 functional component, I want to call parent's function in child component on button click which update parent state. on this function invoke my child component is re-render.so I want Stop this re-rendering, i trying solve it as follow but not working
app.js
import React, { useState, useCallback } from "react";
import Child from "./child";
export default function App()
{ let [show, setShow] = useState(false);
console.log("App Re-render:", show);
const setMyState = useCallback(() => {
setShow(!show);
});
return (
<div className="App">
<h1>Parent Component</h1>
<h2>----------------------------------</h2>
<Child func={setMyState}></Child>
</div>
);
}
child.js
import React, { memo } from "react";
function Child({ func }) {
console.log("Child re-render");
return (
<div>
<p>Child Component</p>
<button onClick={func}>Call Parent Method </button>
</div>
);
}
export default memo(Child);
this "func" function should call multiple time.
please help me to solve this problem

The code you posted looks good. Do you have more code that isn't posted? Can you try to reproduce in an example?
You don't need the useCallback hook to do the functionality you are looking for. So skip that.
I have done the same thing here and it works:
https://codesandbox.io/s/gallant-hellman-60lw3d?file=/src/App.js

Related

How do I get hot reloading to work when passing in functional components as props?

App.tsx
import "./styles.css";
import { Parent } from "./components/parent";
import { Child } from "./components/child";
export default function App() {
return <Parent child={Child} />;
}
Parent.tsx
import * as React from "react";
export const Parent: React.FC<{ child: React.FC }> = ({ child }) => {
return (
<div>
Hot Reload Works
{child({})}
</div>
);
};
Child.tsx
import * as React from "react";
export const Child: React.FC = () => {
return <div>Hot Reload Does Not Work</div>;
};
How do I enable Hot Reload for my Child Functional Component when passing it as a parameter to the Parent? I've included the code sandbox that shows that hot reloading does not work in the child component.
Code Sandbox
Hot reloading allows you to see the changes that you have made in the code without reloading your entire app. As soon as you save your code, React tracks which files have changed since your last saved, and only reload those file for you.
Since you are passing the Child component as a prop function, it will only trigger changes in Child and will reload it. you are not changing the Parent component so it wont reload the changes made in the child({}) function.
The way to solve it is to pass the Child component as a children.
Parent.tsx
export const Parent: React.FC = ({ children }) => {
return (
<div>
Hot Reload Works
{children}
</div>
);
};
App.tsx
export default function App() {
return (
<Parent>
<Child />
</Parent>
);
}

Passing State as Prop

I want to a button show in some child components and don't show in other components. I used useState in parent component but couldn't pass it to child components. How can I do that?
const [showRepo, setShowRepo] = useState(false);
const handleShowRepo = () => {
setShowRepo = !showRepo;
};
Where I use it;
<button className={!showRepo ? `${styles.viewRepo} ${styles.hideRepo}` : `${styles.viewRepo}`}>
<a target="_blank" href={`${props.link}`}>
{props.buttonText}
</a>
</button>
Here's an example as to how to pass a parent component state for a child component to use:
import React, { useCallback, useEffect, useState } from "react";
export function Parent() {
const [name, setName] = useState("Dolan The Duck");
return (
<div>
<h1>Dolan Family</h1>
<Child name={name} />
</div>
);
}
function Child(props) {
return <h2>I am Luffy! {props.name}'s son!</h2>;
}
Let's break down this example:
The Parent component has a name state, when it renders the Child component it passes the state variable as a prop named name.
The Child component uses the prop name to render a cool heading, it does props.name.
Learn more here

why components state data are gone in conditional rendering

I am new to react and come from a background of functional component only.
In my react project,
When I conditionally rendering , ie from false to true, the data inside child component will be gone.
Then I wonder why is that.
Then I heard a concept called unmounting. It means, when my condition change from true to false, the component will get unmounting. And in unmounting, the state inside will gone.
But then, it doesn't add up.
Q: Whenever we re-render any other components, just like the normal situation, we will also unmount component in order to do re-rendering. And our state value would not be gone.
Why this problem was happened especially on having conditional statement in react?
Edit:
My emphsis is not on how to avoid state loss. My question is that why data will be gone in conditional rendering. And why unmounts will cause such problem, but re rendering would not cause such ( both also involves unmounting)
Here is my code
In parent:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import Child1 from "./child";
import "./styles.css";
function Parent() {
const [message, setMessage] = useState("initial text");
const [showChild,setShowChild] = useState(true);
useEffect(() => {
console.log("useeffect in parent");
});
return (
<div className="App">
<button onClick={() => setShowChild(!showChild)}>show child</button>
{showChild?
<Child1 />
:
null
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
In child:
import React, { useEffect, useState } from "react";
function Child1() {
useEffect(() => {
console.log("useeffect in child");
console.log("newMessage: " + newMessage);
});
const [newMessage, setNewMessage] = useState("");
return (
<div>
<input onChange={(event) => setNewMessage(event.target.value)} />
</div>
);
}
export default Child1;
Add some picture to illurste what I mean by data lose in conidtional rendering
enter
https://i.stack.imgur.com/UrIhT.png
click to not show it
https://i.stack.imgur.com/0OC87.png
click to show again
https://i.stack.imgur.com/4zlWk.png
Try moving all state management to the parent component and leave the child component 'dumb'. You can pass the setMessage and any other state variables to the child as props.
Parent:
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import Child1 from "./child";
import "./styles.css";
function Parent() {
const [message, setMessage] = useState("initial text");
const [showChild,setShowChild] = useState(true);
useEffect(() => {
console.log("useeffect in parent");
});
return (
<div className="App">
<button onClick={() => setShowChild(!showChild)}>show child</button>
{showChild?
<Child1 setMessage={setMessage}/>
:
null
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
Child:
import React from "react";
function Child1({setMessage}) {
return (
<div>
<input onChange={(event) => setMessage(event.target.value)} />
</div>
);
}
export default Child1;
The answer for your question is very simple, While unmounting you are removing the component itself from react-dom. The state, props and all the data's handled inside your component will be active only If the component is inside the react-dom. If the particular component is unmounted, all the states and props that was created and processed will also be removed from react-dom along with the component. And the fresh component, state and props will be mounted in the react-dom if you conditionally render the component again.

How to pass an Array from Child component to Parent component in react I know how to pass from parent t

I am working on a React project in that I am trying to pass an array from the child component to the parent component. But I don't know how to pass it
This is Parent component
import React from 'react';
import Child from './Child/Child'
function App() {
return(
<div className='App'>
<Child></Child>
</div>
)
}
export default App
This is Child component
import React from 'react';
function Child() {
const employees = ['Williams','Steve']
return(
<div className='Child'>
</div>
)
}
export default Child
````
You can make use of hooks here.
Initialize a useState hooks in the parent component,
then pass the set method as a prop to the child component.
Then in the child component you can assign new array value to the parent using the set method.
eg:
In parent:
import React, {useState} from 'react';
import Child from './Child/Child'
function App() {
const [arr, setArr] = useState([]);
return(
<div className='App'>
<Child setArrFunc={setArr}></Child>
</div>
)
}
export default App
In child component:
import React, {useEffect} from 'react';
function Child({setArrFunc}) {
const employees = ['Williams','Steve']
useEffect(()=> {
setArrFunc(employees);
},[]);
return(
<div className='Child'>
</div>
)
}
export default Child;
//Or you can make use of onClick Function and make use of the setArrFunc inside clickHandle method
If you want to pass something to the parent component the easiest way is to create a callback in Parent component that you use in Child component.
Pass props to parent component in React.js
In the parent define a method to handle the array:
import React from 'react';
import Child from './Child/Child'
function App() {
const doSomething = (inputArray: string[]) => {
// Do something with your array of strings in here
};
return (
<div className='App'>
<Child doSomethingMethod={this.doSomething}></Child>
</div>
);
}
export default App;
Then you can utilise it in the child:
import React from 'react';
function Child() {
const employees = ['Williams','Steve'];
const doingSomething = () => {
// blah blah
// this method is an example where it takes the employees array as a fixed
// array predefined elsewhere (above)
this.props.doSomethingMethod(employees);
};
const doSomethingElse = (inputArray: string[]) => {
// this method takes arguments then pushes them into the method to pass
// to the parent
this.props.doSomethingMethod(inputArray);
};
return (
<div className='Child'></div>
);
}
export default Child

Getting child properties of a react function component

I have created a simple sample here:
https://codesandbox.io/s/crimson-monad-r6tns?fontsize=14&hidenavigation=1&theme=dark
When you click the text 1 it increment the value in the child component. In the parent i have a button where I want to access the value in the child component from the parent component. Not with an event but something like ChildComponent.YourCurrentValue. Is that possible in REACT? Can you add an id to the child component in the render method and then access it's properties by that?
You have to pass the changes to the parent by calling a prop function in child like this:
import React, { useState } from "react";
const ChildComponent = props => {
const [selectedValue, setSelectedValue] = useState(1);
function clicked() {
const newCounter = counter + 1;
setSelectedValue(newCounter);
props.onChange(newCounter)
}
return <div onClick={clicked}>{selectedValue}</div>;
};
export default ChildComponent;
And get it back in parent component such as below:
import React from "react";
import "./styles.css";
import ChildComponent from "./ChildComponent";
export default function App() {
function showChildProperty(newCounterValue) {
alert(newCounterValue);
}
return (
<div className="App">
<button onClick={showChildProperty}>Show child property</button>
<ChildComponent onChange={showChildProperty} />
</div>
);
}
Hope you found your answer as you wanted.

Resources