React Components child component render twice - any way to fix this? - reactjs

When i click on Update Key button then Child1 component render every time so how can i resolve it.
Note : I have create three component one parent component and two child component when i click on
parent component button to update child component, so child1 component increase to display
multiple time. so please resolved this as soon as possible.
When i click on Update Key button then Child1 component render every time so how can i resolve it.
Note : I have create three component one parent component and two child component when i click on
parent component button to update child component, so child1 component increase to display
multiple time. so please resolved this as soon as possible.
import React, { useState } from "react";
import ReactDOM from "react-dom";
class Child1 extends React.Component {
componentDidMount() {
console.log("mounted");
}
render() {
console.log("rendered");
return <div>Child</div>;
}
}
class Child2 extends React.Component {
componentDidMount() {
console.log("mounted2");
}
render() {
console.log("rendered2");
return <div>Child2</div>;
}
}
class App extends React.Component {
state = {
counter: 0,
counter2: 0
};
onCounter = () => this.setState({ counter: this.state.counter + 1 , counter2: this.state.counter2 + 1 });
render() {
return (
<>
<Child1 key={this.state.counter} />
<Child2 key={this.state.counter2} />
<button onClick={this.onCounter}>Update Key</button>
</>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));

my first response, I think I understand the question, I rewrote it using react hooks as it makes it easier to read and requires no configuration changes just make sure your running the latest version of react.
import React, { useState } from "react";
import ReactDOM from "react-dom";
function Child1(props) {
return <h1>Child{props.input}</h1>;
}
function Child2(props) {
return <h1>Child{props.input}</h1>;
}
function App() {
let [counter, setCounter] = useState(0);
let [counter2, setCounter2] = useState(1);
let onCounter = () => {
setCounter(counter+1)
setCounter2(counter2+1)
}
return (
<>
<Child1 input={counter} />
<Child2 input={counter2} />
<button onClick={onCounter}>Update Key</button>
</>
);
}
ReactDOM.render(<App />, document.getElementById("root"));

It is because your Child component, i.e., Child1 and Child2 are using the same value as key. Both counter and counter2 states have the same value and it is creating ambiguity in the ReactDOM. Here, you are not iterating over an array so there's is no need of using the key property. It will work fine. If you've to use the key property, make sure they are unique at the same level.
~Prayag

Related

Is it possible for me to pass a prop from a child to a parent component on page load?

How can i pass the hello const value which is in the ChildComponent to the App component and store it in the childProps variable of the App component on page load.
import React, { Component } from 'react';
class App extends Component {
render() {
var childProps ''; // I want store the passed const value in this variable;
return (
<div>
<ChildComponent />
</div>
);
}
}
export default App;
class ChildComponent extends Component {
render() {
const hello = 'Hope you are having a good day!';
return <h1>{hello}</h1>;
}
}
export default ChildComponent;
There is no way to pass props from a child component to a parent component. However, we can always pass around functions from the parent to child component. The child component can then make use of these functions.
You can assign a callback to child component from parent component, it will be called once the child is mounted. Store that value in parent class property , if re-render requires maintain a state.
App
class App extends Component {
helloCallback = (str) => {
this.childProps = str
}
render() {
return (
<div>
<ChildComponent helloCallback={helloCallback}/>
</div>
);
}
}
Child
class ChildComponent extends Component {
hello = 'Hope you are having a good day!'
componentDidMount() {
this.props.helloCallback(this.hello)
}
render() {
return <h1>{this.hello}</h1>;
}
}

How can i refresh my child componet by using a button click on parent componet?

I am new to this stackoverflow world. Please help me here. How can i refresh the child component based on the button click from the parent component. For example, i have a button in parent component called refresh and not passing any state variables or props to child component. but i want the child component to loaded again based on the button click of parent. I tried adding a state variable, but it was not updating the child component.
parent component:
import React from "react";
import ChildComponentForRefreshTesting from "./ChildComponentForRefreshTesting";
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { isRefreshClicked : false };
}
submit() {
this.setState({ isRefreshClicked: true }, () => this.setState({isRefreshClicked: false}));
}
render() {
return (
<div>
<h1>Parent Component ------<button onClick={this.submit}>Refresh</button></h1>
<ChildComponentForRefreshTesting />
</div>
)
}
}
export default MyComponent;
child component:
import React from 'react'
function ChildComponentForRefreshTesting() {
return (
<div>
child component
<br />
</div>
)
}
export default ChildComponentForRefreshTesting;
Changing state should re-render the current component and all the child components inside it.
I ran your code and there is a mistake with how you defined the setState method. You need to use arrow function, otherwise this will be undefined.
So change your submit button like following and it should work.
submit = () => {
this.setState({ isRefreshClicked: true });
};
Here's the stackblitz: https://stackblitz.com/edit/react-f5q3n8?file=src/MyComponent.js
In class components, you can call this.forceUpdate() method to force a rerender.
https://reactjs.org/docs/react-component.html#forceupdate

React - What is meant by 'Do not use HOC’s in the render method of a component. Access the HOC outside the component definition.'?

I am learning HOCs and keep reading the above quote, but I do not understand what it means. If my HOC adds a method to my consuming component, can I use that method in the render method like so? If not how would I do what I am trying to do here:
import React, { Component } from 'react';
import { withMyHOC } from '../with_my_component'
class MyComponent extends Component {
constructor(props) {
super(props);
}
render() {
const { methodFromHOC }= this.props;
const result = methodFromHOC(someArgument);
return (
<div >
{result}
</div>
)
}
}
export default withMyHOC(MyComponent );
When you say, do not use HOC within the render method, it means that you shouldn't create an instance of the component wrapped by HOC within the render method of another component. For example, if you have a App Component which uses MyComponent, it shouldn't be like below
import React, { Component } from 'react';
class MyComponent extends Component {
constructor(props) {
super(props);
}
render() {
const { methodFromHOC }= this.props;
const result = methodFromHOC(someArgument);
return (
<div >
{result}
</div>
)
}
}
export default MyComponent;
import { withMyHOC } from '../with_my_component'
export default class App extends React.Component {
render() {
const Wrap = withMyHOC(MyComponent);
return (
<div>
{/* Other Code */}
<Wrap />
</div>
)
}
}
Why you shouldn't use it like above is because everytime render method is called a new instance of the MyComponent is created wrapped by HOC called Wrap and hence everytime it be be mounted again instead of going by the natural lifecycle or React.
However if your HOC passes a function as props, you can use it within the render as long as it doens't cause a re-render again otherwise it will lead to a infinite loop.
Also its better to memoize functions which are called in render directly to avoid computation again and again
CodeSandbox Demo
A High Order Component is a function which returns a Component, not jsx. When wrapping a component with an hoc, you're not changing the returned value of your component, you're changing the signature itself. Consider the following hoc
const withFoo = Component => props =>{
return <Component {...props} foo='foo' />
}
withFoo is a function which takes a Component (not jsx) as argument and returns a component. You don't need to call an hoc from render because the values it injects are already inside props of the wrapped component.
An hoc tells how a wrapped component will look like, changes it's definition so the only place to use it is in the component definition itself. Calling an hoc inside render creates a new instance of that component on each render. It's the equivalent of
const Component = () =>{
const ChildComponent = () =>{
return <span> Child </span>
}
return <ChildComponent /> //You're declaring again on each render
}
Use your high order components like this
const Component = ({ foo }) => <div>{ foo }</div>
export default withFoo(Component)
Or
const Component = withFoo(({ foo }) => <div>{ foo }</div>)

Extend React lifecycle hook (e.g add a print statement on every ComponentDidMount)

I want to add some behaviour on a given lifecycle hook of a React application.
For example, adding a console.log('Component is mounted') on every ComponentDidMount of all the components of an application, without having to define it in every one of them (as a decorator for example), sort of like a global extender of that method that adds some code to it. Like that: Extending Vue Lifecycle Hooks but for React.
Anyone has an idea on how to achieve that? Cheers!
You can use hoc. In the root app, apply the higher order component.
Example:
const withMountHOC = WrappedComponent => {
return class extends Component {
componentDidMount() {
console.log('mounted');
}
render() {
return <WrappedComponent {...this.props} />
}
}
}
export default withMountHOC;
In your app component:
const WrappedApp = withMountHOC(App);
ReactDOM.render(
WrappedApp,
document.getElementById('root')
);
Since the parent componentDidMount hook is called after child componentDidMount hook, the HOC componentDidMount will be applied in any nested level of the component.
You may also be interested to see this blog: Replacing Mixins in React.
create CustomComponent.js
import React, { Component } from 'react'
class CustomComponent extends Component {
constructor(props){
super();
}
componentDidMount(){
console.log('component is mounted');
}
render () {
return (
<div>
{this.props.children}
</div>
)
}
}
export default CustomComponent
Now create MyComponent.js that extends CustomComponent.js
import React, { Component } from 'react'
import CustomComponent from './CustomComponent'
class MyComponent extends CustomComponent {
render () {
return (
<div>
Hello from MyComponent
</div>
)
}
}
export default MyComponent;
now you see console , you have log : "component is mounted"
but if you write componentDidMonunt() inside MyComponent.js , you will get log from MyComponent.js

How to use Higher Order function (or alternative) for wrapping a React component without the component continually unmounting?

I have a React component (Parent) within which there is another componet (Child) that is wrapped using a Higher Order function (HOWrapper). The problem I am having is that each time the Parent component renders, the Child component unmounts and then re-mounts. I need to find a way that prevents the Child component from unmounting, but still continue to wrap it in a component whose name is dynamically assigned. I also want the option to pass additional parameters to the HOWrapper function, that may also be dynamically generated in the render() function of Parent. Any ideas?
Parent component:
import { HOWrapper } from './somepath';
import Child from './someotherpath';
export default class Parent extends Component {
...
render(){
let ChildWrapper = HOWrapper(Child);
return (
<ChildWrapper {...this.props} />
);
}
}
Higher Order function:
export function HOWrapper(WrappedComponent) {
return class Blanket extends Component {
constructor(props) {
super(props);
this.state = {
...
};
}
...
render() {
return (
<WrappedComponent
{...this.props}
/>
);
}
}
}
Because an HOC returns a component, a more typical approach to using them is once when exporting them, not on every render call.
let YourComponent = props => <div />
export default HOC(YourComponent)
Then if you want to do anything dynamic pass new props to it.
render() { return <YourComponent dynamicProps={foo} /> }

Resources