Passing object to parent state from child - reactjs

Is there any way I can push an object to the parent props from the child component?

You can pass a function from the parent to the child that can set the state of an object in the parent.
import React, { Component } from 'react';
import { render } from 'react-dom';
const Child = ({saveObj}) => (
<div
onClick={() => {
saveObj({test: "test"})
}}
>
Click to set obj
</div>
)
class App extends Component {
constructor() {
super();
this.state = {
obj : null
};
}
render() {
return (
<div>
Obj is: {JSON.stringify(this.state.obj)}
<p>
<Child saveObj={obj => {this.setState({obj})}} />
</p>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Live Example: https://stackblitz.com/edit/react-snivhc

Related

Don't change the state in my component - React

I'm trying to change the state the a child component but don't change, this is the parent component:
export default class History extends Component {
constructor(props) {
super(props);
this.state = {
histories : JSON.parse(JSON.stringify(histories)),
counter: 1,
id: ''
}
}
increaseCounter = () => {
this.setState({counter: this.state.counter+1})
}
showIdHistory = (id) => {
this.setState(() => {return {id:id}})
}
render() {
return (
<div className="history">
<div>
<h3 className='titleHistory'>{searchHistoryById(this.state.id,this.state.counter)}</h3>
</div>
<div className='options'>
<div className='option'>
<BottonOptionA option='A' increaseCounter={this.increaseCounter} showIdHistory={this.showIdHistory}/>
<h2>{searchOptionById('a',this.state.counter+this.state.id)}</h2>
</div>
<div className='option'>
<BottonOptionB option='B' increaseCounter={this.increaseCounter} showIdHistory={this.showIdHistory}/>
<h2>{searchOptionById('b',this.state.counter+this.state.id)}</h2>
</div>
</div>
<div className='sectionStatics'>
<SelectionBefore optionAnterior={this.state.id}/>
<reacordOfOptions option={this.state.id}/>
</div>
</div>
);
}
}
i want that the parent component pass the state to the component called SelectionBefore but when the parent child changes the state, the props of SelectionBefore still is the same
this is the component child:
import React,{Component} from 'react'
export default class SelectionBefore extends Component {
constructor(props) {
super(props)
this.state = {
optionBefore : props.optionBefore,
}
}
render() {
return (
<div >
<p> Seleccion anterior: {this.state.optionBefore}</p>
</div>
)
}
}
Try following changes :
Child component
import React,{Component} from 'react'
export default class SelectionBefore extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div >
<p> Seleccion anterior: {this.props.optionAnterior}</p>
</div>
)
}
}
I have directly used the props which is passed by parent to the child .
This means that , whenever state of parent changes , your child will rerender and the changes will be shown .

How to change title from child component to parent component without hooks?

I have two components child and parent. And I want to change the title of the parent component from the child component. But without hooks.
So I have this:
class App extends Component {
render() {
return (
<div className="app">
<ParentComponent/>
</div>
);
}
}
export default App;
and child component:
import React from 'react'
function ChildComponent(props) {
return (
<div>
<h1>Child COmponent</h1>
<button onClick={() => props.greetHandler('Niels')}>Greet parent</button>
</div>
)
}
export default ChildComponent;
and parent component:
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
parentName: 'parent'
};
this.greetParent = this.greetParent.bind(this);
}
greetParent(childname) {
`${childname}`;
}
render() {
return (
<div>
<h1>{this.state.parentName}</h1>
<ChildComponent greetHandler={this.greetParent} />
</div>
)
}
}
export default ParentComponent;
But nothing happens And I got the message:
./src/ParentComponent.js
Line 19: Expected an assignment or function call and instead saw an expression no-unused-expressions
So my question: what I have to change that the title of parent component will change to Niels
you should change the state in greetParent function
greetParent(childname) {
this.setState({
parentName: childname
})
}

How to pass the data from child to parent? when parent is class based and child is functional based

I want to pass the data which is anything like, array, strings, numbers into the App(Parent) Component) from the Child1(Child) components.
There's a parent who is class-based and the child is functional based.
Parent:
import React, { Component } from "react";
import "./App.css";
import Child1 from "./Child1/Child1";
class App extends Component {
state = { message: "" };
callbackFunction = (event) => {
this.setState({
message: event.target.value
});
}
render() {
return (
<div className="App">
<Child1 />
</div>
);
}
}
export default App;
Child
import React from 'react'
const Child1 = (props) => {
return (
<div>
</div>
);
}
export default Child1;
If you want to send some data to the parent component upon clicking a button that's in the child component, you can do it this way:
import React from 'react'
const Child1 = React.memo((props) => {
return (
<div>
<button onClick={() => {props.clicked('some data')}} type="button">Click me to send data<button>
</div>
);
})
export default Child1;
now you can assign a function to the clicked prop in your parent component and that gets called when the button in the child component is clicked:
class App extends Component {
state = { message: "" };
callbackFunction = (event) => {
this.setState({
message: event.target.value
});
}
clicked = (data) => { // this func. will be executed
console.log(data);
}
render() {
return (
<div className="App">
<Child1 clicked={this.clicked}/>
</div>
);
}
}
I have founded another solution for you using combine Functional-Class-functional component pass data. here the live code for https://codesandbox.io Click and check that.
Also same code added bellow here:
app component
import React, { useState } from "react";
import "./styles.css";
import Child from "./child";
export default function App() {
const [name, setName] = useState("Orignal Button");
const [count, setCount] = useState(0);
const handleClick = _name => {
setName(_name);
setCount(count + 1);
};
const resetClick = e => {
setName("Orignal Button");
setCount(0);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Child
name={name + " - " + count}
handleClick={handleClick}
resetClick={resetClick}
/>
</div>
);
}
child1 component
import React from "react";
import Child2 from "./child2";
class Child extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<h2>This is child</h2>
<button onClick={e => this.props.handleClick("New Name changed")}>
{this.props.name}
</button>
<Child2 handleChilc2Click={this.props.resetClick} />
</>
);
}
}
export default Child;
Another component Child2
import React from "react";
const Child2 = props => {
return (
<>
<h2>Child 2</h2>
<button onClick={e => props.handleChilc2Click(e)}>
Click me for reset Parent default
</button>
</>
);
};
export default Child2;
You can some help from it.
Thanks
You can pass a function to Child (called Counter in the example) that will change Parent state. Since you pass the same reference for this function every time (this.increment) the only Children that will render are those that changed.
const Counter = React.memo(
//use React.memo to create pure component
function Counter({ counter, increment }) {
console.log('rendering:', counter.id)
// can you gues why prop={new reference} is not a problem here
// this won't re render if props didn't
// change because it's a pure component
return (
<div>
<div>counter is {counter.count}</div>
<button onClick={() => increment(counter.id)}>
+
</button>
</div>
)
}
)
class Parent extends React.PureComponent {
state = {
counters: [
{ id: 1, count: 0 },
{ id: 2, count: 0 }
]
}
increment = _id =>
this.setState({
counters: this.state.counters.map(val =>
_id === val.id
? { ...val, count: val.count + 1 }
: val
)
})
render() {
return (
<div>
{this.state.counters.map(counter => (
<Counter
counter={counter}
increment={this.increment}
key={counter.id}
/>
))}
</div>
)
}
}
//render app
ReactDOM.render(<Parent />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Adding child component on onClick of parent component again and again with new prop every time to child comp

I am new to react so bear any nontechnical words. I have a parent component which has a button element on onClick of button a function is called which creates a new object. what I want is also to happen when user clicks on this button child component should be renderd below parent button element and every time button is clicked new object should be passed as prop to child component so it can display it on screen, but previous called child should remain on screen.
import React from 'react';
class childcomponent extends React.PureComponent{
state = { data: this.props.data }
render(){
return(
<div>
<span>Name: {this.state.data.name}</span>
<span>Lastname: {this.state.data.lastname}</span>
</div>
)
}
}
class Parentcomponent extends React.PureComponent{
handleAddChild=(e)=>{
e.preventDefault();
//Here i form the object
const user = {
//key:value
}
//want to render child component from here
}
render(){
return(
<div>
{/* //some code
//some code
//some code */}
<button onClik={this.handleAddChild} >Save</button>
{/* //want to render child component here </childcomponent> */}
</div>
);
}
}
here is a trick
make a state for children
this.state = {
children: []
}
then loop to render
renderChildren = () => {
return this.state.children.map(item => {
return <Child />
})
}
and add children
handleAddChild=(e)=>{
e.preventDefault();
//Here i form the object
const user = {
//key:value
}
this.setState({children: [...this.state.children, user]})
}
In react you will need to think in a way, that your JSX( html+js) is already prepared to display child component and only waits for state to display it. First of all, you will need state of parent component with some empty object
state = { child: {} )
then in you render method
{!!this.state.child && <Childcomponent data={this.state.child}}
then your add method
addChild = () => this.setState({ child: {name: 'Hi', surname: 'Hello'} })
Create an array in parent component and store the same as State value of the parent component,
pass this array as props to the child component
loop through the array in child component to make as much as list component
Child Component
let List=this.props.data.map(item=>(
<div>
<span>Name: {this.state.data.name}</span>
<span>Lastname: {this.state.data.lastname}</span>
</div>
))
render(){
return(
<List/>
)
}
}````
Below is the working code for your question and codesandbox link:-
App.jsx
import React from "react";
import ReactDOM from "react-dom";
import ChildComponent from "./Child";
import "./styles.css";
class App extends React.Component {
state = {
user: [
{ name: "name1", lastname: "lastname1", key: 1 },
{ name: "name2", lastname: "lastname2", key: 2 },
{ name: "name3", lastname: "lastname3", key: 3 }
],
data: [],
count: 0
};
handleAddChild = e => {
e.preventDefault();
this.setState({
data: [...this.state.data, this.state.user[this.state.count]],
count: this.state.count + 1
});
};
render() {
console.log("data", this.state.data);
return (
<div className="App">
<button onClick={this.handleAddChild}>Save</button>
{this.state.data.length &&
this.state.data.map(item => {
return <ChildComponent data={item} />;
})}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Child.js
import React from "react";
class childcomponent extends React.PureComponent {
state = { data: this.props.data };
render() {
return (
<div key={this.state.data.key}>
<span>Name: {this.state.data.name}</span>
<br />
<span>Lastname: {this.state.data.lastname}</span>
</div>
);
}
}
export default childcomponent;
Hope that helps!!!

Typescript + React call parent method from child component

I am trying to call parent method from child component, but it doesn't work and method in parent element is not triggered. In this example I have only two components where ChildHello calls method in Hello component.
codesandbox
Hello.tsx
import * as React from "react";
interface Props {
itemClicked: () => void;
}
export class Hello extends React.Component<Props, {}> {
constructor(props: Props) {
super(props);
}
itemClicked = val => {
console.log(val);
};
render() {
const { name } = this.props;
return <h1 itemClicked={this.itemClicked}>{this.props.children}</h1>;
}
}
const styles = {
height: "400px"
};
export class ChildHello extends React.Component<Props, {}> {
constructor(props: Props) {
super(props);
}
render() {
return (
<div onClick={this.props.itemClicked} style={styles}>
<Hello>Hello Child</Hello>
</div>
);
}
}
You need to understand parent child relationship
in childHello you are using the click event.
<div onClick={this.props.itemClicked} style={styles}>
<Hello>Hello Child</Hello>
</div>
childhello is called by the index.jsx page
<div style={styles}>
<ChildHello name="CodeSandbox" />
</div>
Here you are not passing any click events. also, hello component is inside the child component which is wrong.
All the parent component should have click method involved and that method should be passed as props.
Like this
Parent:
<div style={styles}>
<Hello name="CodeSandbox" />
</div>
Hello component
render() {
const { name } = this.props;
return <ChildHello itemClicked={this.itemClicked} />;
}
ChildHello
render() {
return (
<div onClick={this.props.itemClicked} style={styles}>
Hello
</div>
);
}
Sandbox demo

Resources