How to re-render parent component from child component - javascript

parent component has a p tag which animate it's inner text. animation works when i refresh the page.
here is the Parent component:
import React, { Component } from 'react';
import Child from './Child';
class Parent extends Component {
rerender=()=>{
this.forceUpdate()
}
render() {
return (
<div>
<p className='animate-left'>Animation</p>
<Child rerender={this.rerender}/>
</div>
);
}
}
export default Parent;
here is the Child component:
import React, { Component } from 'react';
class Child extends Component {
clickHandler=()=>{
this.props.rerender()
}
render() {
return (
<div>
<button onClick={this.clickHandler}>Click</button>
</div>
);
}
}
export default Child;
i want to animate again/ re-render parent component by clicking the button of child component.
How to do that?

You have to have state in the parent component and pass down this state to the child component:
import React, { Component } from "react";
import Child from "./Child";
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
rerender = () => {
this.forceUpdate();
};
forceUpdate = () => {
this.setState((state) => ({
counter: state.counter + 1
}));
};
render() {
console.log("got rendered");
return (
<div>
<p className="animate-left" key={this.state.counter}>Animation</p>
<Child rerender={this.rerender} />
</div>
);
}
}
export default Parent;
and in the child component update this state:
import React, { Component } from "react";
class Child extends Component {
clickHandler = () => {
this.props.rerender();
};
render() {
return (
<div>
<button onClick={this.clickHandler}>Click</button>
</div>
);
}
}
export default Child;

Related

How to find the Parent Component name in ReactJS v16.11

I have a one react component which is nested inside a multi-level components and each of these components are getting a props from their parent components. As it was multi level nesting, I lost track of the parent component.
So, are there any ways to find, from which parent component we are getting the props to its child?
I tried with the below code. But it is not working.
this._reactInternalInstance._currentElement._owner._instance
Scenario:
First Component:
import React, { Component } from 'react'
import SecondLevelComponent from './SecondLevelComponent'
export class FirstLevelComponent extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
<SecondLevelComponent data="From Main Parent Component" />
</div>
)
}
}
export default FirstLevelComponent
Second Component:
import React, { Component } from 'react'
import ChildComponent from './ChildComponent'
export class SecondLevelComponent extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
<ChildComponent data2={this.props.data}/>
</div>
)
}
}
export default SecondLevelComponent
Child Component:
export class ChildComponent extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
<h1>FROM PARENT TO CHILD {this.props.data2}</h1>
</div>
)
}
}
export default ChildComponent

React pass child class method to parent functional component

I am trying to get adaptValue from Component1 and use it in Component2. For some reason this does not work since my adaptValue is always null/undefined. Is it because Parent is a functional component?
const Parent = (props) => {
const [adaptValue, setAdapt] = useState(null);
return (
<div>
<Component1 setAdapt={setAdapt}/>
<Component2 adaptValue={adaptValue}/>
</div>
)
}
export default class Component1 extends Component {
constructor(props) {
super(props);
}
adaptValue = (value) =>{
DO_SOMETHING_WITH_VALUE
}
componentDidMount() {
this.props.setAdapt(this.adaptValue);
}
render() {
return something;
}
}
export default class Component2 extends Component {
constructor(props) {
super(props);
}
someFunction = (value) =>{
...
//adaptValue is always undefined
this.props.adaptValue(value)
...
}
render() {
return something;
}
}
UPDATE Made the parent a class component in the end and all works. Wondering whether this is a compatibility issue between functional or class-based components.
When passing setAdapt to Component1 ... setAdapt is already a function. There is no need to wrap it in another one. Component1 will modify the value, and Component2 will display it. Function Components have nothing to do with the behavior.
Try ...
App.js
import React, { useState } from "react";
import "./styles.css";
import Component1 from "./Component1";
import Component2 from "./Component2";
export default function App() {
const [adaptValue, setAdapt] = useState(null);
return (
<div>
<Component1 setAdapt={setAdapt} />
<Component2 adaptValue={adaptValue} />
</div>
);
}
Component1.js
import React, { Component } from "react";
export default class Component1 extends Component {
handleClick = () => {
this.props.setAdapt("New Value");
};
render() {
return <button onClick={() => this.handleClick()}>Set Value</button>;
}
}
Component2.js
import React, { Component } from "react";
export default class Component2 extends Component {
render() {
return !!this.props.adaptValue ? (
<h1>{`"${this.props.adaptValue}" <- Value of adaptValue`}</h1>
) : (
<h1>adaptValue Not Assigned</h1>
);
}
}
Sandbox Example ...

Can i pass component state to HoC?

Is there any way to send data from the component's state to HoC?
My component
import React, { Component } from 'react';
import withHandleError from './withHandleError';
class SendScreen extends Component {
contructor() {
super();
this.state = {
error: true
}
}
render() {
return (
<div> Test </div>
)
}
};
export default withHandleError(SendScreen)
My HoC component:
import React, { Component } from 'react';
import { ErrorScreen } from '../../ErrorScreen';
import { View } from 'react-native';
export default Cmp => {
return class extends Component {
render() {
const { ...rest } = this.props;
console.log(this.state.error) //// Cannot read property 'error' of null
if (error) {
return <ErrorScreen />
}
return <Cmp { ...rest } />
}
}
}
Is there any way to do this?
Is the only option is to provide props that must come to the SendScreen component from outside??
A parent isn't aware of child's state. While it can get an instance of a child with a ref and access state, it can't watch on state updates, the necessity to do this indicates design problem.
This is the case for lifting up the state. A parent needs to be notified that there was an error:
export default Cmp => {
return class extends Component {
this.state = {
error: false
}
onError() = () => this.setState({ error: true });
render() {
if (error) {
return <ErrorScreen />
}
return <Cmp onError={this.onError} { ...this.props } />
}
}
}
export default withHandleError(data)(SendScreen)
In data you can send the value you want to pass to HOC, and can access as prop.
I know I answer late, but my answer can help other people
It is very easy to do.
WrappedComponent
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import HocComponent from './HocComponent';
const propTypes = {
passToHOC: PropTypes.func,
};
class WrappedComponent extends Component {
constructor(props) {
super(props);
this.state = {
error: true,
};
}
componentDidMount() {
const {passToHOC} = this.props;
const {error} = this.state;
passToHOC(error); // <--- pass the <<error>> to the HOC component
}
render() {
return <div> Test </div>;
}
}
WrappedComponent.propTypes = propTypes;
export default HocComponent(WrappedComponent);
HOC Component
import React, {Component} from 'react';
export default WrappedComponent => {
return class extends Component {
constructor() {
super();
this.state = {
error: false,
};
}
doAnything = error => {
console.log(error); //<-- <<error === true>> from child component
this.setState({error});
};
render() {
const {error} = this.state;
if (error) {
return <div> ***error*** passed successfully</div>;
}
return <WrappedComponent {...this.props} passToHOC={this.doAnything} />;
}
};
};
React docs: https://reactjs.org/docs/lifting-state-up.html
import React, { Component } from 'react';
import withHandleError from './withHandleError';
class SendScreen extends Component {
contructor() {
super();
this.state = {
error: true
}
}
render() {
return (
<div state={...this.state}> Test </div>
)
}
};
export default withHandleError(SendScreen)
You can pass the state as a prop in your component.

componentDidMount firing before DOM is mounted when using createPortal in React

I have a code like this in my React application:
import React from 'react';
import ReactDOM from 'react-dom';
import ComponentB from './ComponentB';
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.condition = this.props.condition;
}
render() {
return ReactDOM.createPortal(
<div id="abc"></div>,
document.getElementById('xyz'))
}
componentDidMount() {
ReactDOM.createPortal(
<div>
{
this.condition &&
<ComponentB />
}
</div>,
document.body)
}
}
Basically, I want to render ComponentB only after ComponentA has been mounted to DOM. Hence I have put the code for ComponentA inside componentDidMount of ComponentB. But still ComponentB is rendering before ComponentA has finished mounting to DOM.
Why is this happening and what's the solution to this problem?
I am not sure why you are using createPortal. But if you just want to achieve your goal, you just need to set your state condition in componentDidMount of first component telling to start rendering of your second component.
See if this helps.
const ComponentB = () => {
return (
<div>Hi is is componentB</div>
);
}
class ComponentA extends React.Component {
constructor(props) {
super (props);
this.state = {
renderB: false
};
}
componentDidMount() {
this.setState({
renderB: true
});
}
render () {
let {renderB} = this.state;
return (
<div>
<h3>Hey i am component A</h3>
{
renderB? <ComponentB /> : null
}
</div>
);
}
}

React.js - How to implement a function in a child component to unmount another child from the same parent, and mount another component on it's place?

For example, a component like this:
import React, { Component } from 'react';
import BodyContent from './BodyContent';
import BottomOne from './BottomOne';
import BottomTwo from './BottomTwo';
class App extends Component {
render() {
return (
<div className="App">
<BodyContent />
<BottomOne />
</div>
);
}
}
export default App;
I want to implement a function on BodyContent that unmount BottomOne and mounts BottomTwo instead, so when I activate the function, the code is reestructured to this:
import React, { Component } from 'react';
import BodyContent from './BodyContent';
import BottomOne from './BottomOne';
import BottomTwo from './BottomTwo';
class App extends Component {
render() {
return (
<div className="App">
<BodyContent />
<BottomTwo />
</div>
);
}
}
export default App;
I'm very new to React, so if there's a better way to do it, I'm open to suggestions, but I really need that end result, a function on BodyContent that unmounts BottomOne and mounts BottomTwo.
You can maintain a state which tells which component to render. Something roughly like this
import React, { Component } from 'react';
import BodyContent from './BodyContent';
import BottomOne from './BottomOne';
import BottomTwo from './BottomTwo';
class App extends Component {
changeBottomComponent = (comp) => {
this.setState({ showBottom: comp})
}
render() {
return (
<div className="App">
<BodyContent changeBottomComponent={this.changeBottomComponent}/>
{this.state.showBottom === 1 ? <BottomOne /> : <BotttomTwo />}
</div>
);
}
}
export default App;
To achieve that maintain a state variable in parent component (some kind of identifier for component) and use that state variable to render different component.
Along with that you also need to pass a function from parent to child and use that function to update the parent state value.
Like this:
class App extends Component {
constructor(){
super();
this.state={
renderOne: true,
}
this.update = this.update.bind(this);
}
update(){
this.setState({renderOne: false})
}
render() {
return (
<div className="App">
<BodyContent update={this.update}/>
{this.state.renderOne? <BottomOne /> : <BottomTwo/> }
</div>
);
}
}
Now inside BodyContent component call this.props.update() to render another component.
You can use state or props to render different components.
Example:
import React, {
Component
}
from 'react';
import BodyContent from './BodyContent';
import BottomOne from './BottomOne';
import BottomTwo from './BottomTwo';
class App extends Component {
constructor(props) {
super(props);
this.state = {
decider: false
};
}
render() {
const bottomContent = this.state.decider === true ? <BottomOne /> : <BottomTwo />;
return (
<div className="App">
<BodyContent />
{ bottomContent }
</div>
);
}
}
export
default App;
You can also directly use the components in the state and render them. Could be more flexible this way.
const BottomOne = () => <div>BottomOne</div>;
const BottomTwo = () => <div>BottomTwo</div>;
class Example extends React.Component {
constructor() {
super();
this.state = { show: BottomOne };
this.toggleComponent = this.toggleComponent.bind(this);
}
toggleComponent() {
// Use whatever logic here to decide.
let show = BottomOne;
if (this.state.show === BottomOne) {
show = BottomTwo;
}
this.setState({ show });
}
render() {
return (
<div>
<button onClick={this.toggleComponent}>Change</button>
<this.state.show />
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Categories

Resources