So I have a component "itemSelection" and inside of it I map through an api response like this
<div className="row">
{this.state.items.map(i => <Item name={i.name} quantity={i.quantity} />)}
</div>
Here the state of "Item" component
constructor(props){
super(props);
this.state = {
visible: false,
selected: false,
}
}
How could I pass the state of "Item" component to "itemSelection" component?
Sending data back up to your parent component should be done by using props.
Fairly common question, see this post for the long answer.
As according to me, If I understood your question you want to call the state of the child component to the parent component.
//Child.js
import s from './Child.css';
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
export default withStyles(s)(Child);
//Parent.js
class Parent extends Component {
render() {
onClick() {
this.refs.child.getAlert()
}
return (
<div>
<Child ref="child" />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
Also, you can get the code reference from the link: https://github.com/kriasoft/react-starter-kit/issues/909
This a little tricky but Maybe, its help you solving your problem.
//Parent.js
class Parent extends Component {
component(props) {
super(props)
this.state = {
test: 'abc'
}
}
ParentFunction = (value) => {
this.state.test = value;
this.setState(this.state);
}
render() {
return (
<div>
<Child
test={this.state.test}
ParentFunction={this.ParentFunction}
/>
</div>
);
}
}
//Child.js
import s from './Child.css';
class Child extends Component {
component(props) {
super(props)
this.state = {
test: props.test
}
}
handleChange = () => {
this.state.test = event.target.value;
this.setState(this.state);
this.handleOnSave()
}
handleOnSave = () => {
this.props.ParentFunction(this.state.test);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
</div>
);
}
}
export default withStyles(s)(Child);
Related
So I am quite new to React world, and I have this problem I am trying to solve, but I don't quite understand why it is happening.
So I want to pass the state of component to parent component and from parent component to child component and everything look okay, and in console log the state goes trough, but nothing changes. I believe there is a way I need to listen for state change or something within child component so it works. If I put true in the parent component, child component also get's true, but if I toggle it on click, it goes trough but nothing changes in the child component.
Also I understand my code is little rough right now ill reafactor it later, but right now I am trying to understand why it does not work.
If anyone could help me I would be thankful for it.
This is component that controls the state.. So the state passes from TurnOnBtn to App and from App it goes to TodoList
import "./Todo.css";
class TurnOnBtn extends Component {
constructor(props) {
super(props);
this.state = { display: false };
this.handleState = this.handleState.bind(this);
}
handleState() {
this.setState({ display: !this.state.display });
this.props.checkDisplay(this.state.display);
}
render() {
return (
<button onClick={this.handleState} className="TurnOnBtn">
<i className="fa fa-power-off"></i>
</button>
);
}
}
export default TurnOnBtn;
parent component App
import TurnOnBtn from "./TurnOnBtn";
import TheMatrix from "./TheMatrxHasYou";
import TodoList from "./TodoList";
import { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = { display: true };
this.checkDisplay = this.checkDisplay.bind(this);
}
checkDisplay(newDisplay) {
this.setState({
display: newDisplay,
});
console.log(this.state);
}
render() {
return (
<div className="App">
<TodoList display={this.state.display} />
<TheMatrix />
<TurnOnBtn checkDisplay={this.checkDisplay} />
</div>
);
}
}
export default App;
child component TodoList
import Todo from "./Todo";
import NewTodoForm from "./NewTodoForm";
import { v4 as uuid } from "uuid";
import "./Todo.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
displayOn: this.props.display,
};
this.newTodo = this.newTodo.bind(this);
this.editTodo = this.editTodo.bind(this);
this.deleteTodo = this.deleteTodo.bind(this);
}
editTodo(id, updatedTask) {
const updatedTodo = this.state.todos.map((todo) => {
if (todo.id === id) {
return { ...todo, todo: updatedTask };
}
return todo;
});
this.setState({
todos: updatedTodo,
});
console.log(updatedTask);
}
deleteTodo(id) {
this.setState({
todos: this.state.todos.filter((todo) => todo.id !== id),
});
}
newTodo(newState) {
this.setState({
todos: [...this.state.todos, { ...newState }],
});
}
render() {
return (
<div
style={this.state.displayOn ? { opacity: 1 } : { opacity: 0 }}
className="Todo-screen"
>
{" "}
<div className="TodoList">
<div className="TodoList-todos">
{" "}
{this.state.todos.map((todo) => (
<Todo
key={uuid()}
id={todo.id}
active={todo.active}
editTodo={this.editTodo}
deleteTodo={this.deleteTodo}
todoItem={todo.todo}
/>
))}
</div>
</div>{" "}
<NewTodoForm newTodo={this.newTodo} />
</div>
);
}
}
export default TodoList;
The bug here is in these line of codes:
handleState() {
this.setState({ display: !this.state.display });
this.props.checkDisplay(this.state.display);
}
Remember setState is an async function, so by the time you set a new state using setState, the value for this.state is not guaranteed changed.
One way to fix this is using the setState callback, which will run after the state is changed:
handleState() {
this.setState({ display: !this.state.display }, function() {
this.props.checkDisplay(this.state.display);
});
}
But you don't need to use another state to keep display state in TurnOnBtn as you can pass the toggle callback from the parent:
App.js
class App extends Component {
constructor(props) {
super(props);
this.state = { display: true };
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display,
});
}
render() {
return (
<div className="App">
<TodoList display={this.state.display} />
<TheMatrix />
<TurnOnBtn toggleDisplay={this.toggleDisplay} />
</div>
);
}
}
TurnOnBtn.js
class TurnOnBtn extends Component {
constructor(props) {
super(props);
this.handleState = this.handleState.bind(this);
}
handleState() {
this.props.toggleDisplay();
}
render() {
return (
<button onClick={this.handleState} className="TurnOnBtn">
<i className="fa fa-power-off"></i>
</button>
);
}
}
Is it possible to create a method in Parent class in React and then pass it on to the Child and use it there.
So basically I would create a button in my Parent class, pass the function on to the Child and when the Button is clicked, the child will know about it and Parent will not really care for it?
class App extends Component {
clickMade = () => {
//This should be left empty
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child clickMade={this.clickMade} />
</div>
);
}
}
export default App;
And the Child:
class Child extends Component {
constructor(props) {
super(props);
this.handleClick = this.props.clickMade.bind(this);
}
handleClick = () => {
console.log("Click in child");
}
render() {
return null;
}
}
export default Child;
And a sandbox for this: CodeSandbox
App.js
class App extends Component {
clickMade = () => {
this.childRef.handleClick();
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child
ref={ref => {
this.childRef = ref;
}}
/>
</div>
);
}
}
I have build an input-field component and need to access its value from parent component. I tried something like document.getelementById(id).value, but it'll return null as value.
Parent component:
import StateBox from './StateBox.js';
import React, { Component } from 'react';
export default class AdressenListe extends Component {
render() {
let filteredAdressen = this.props.adressen.filter(
(asingle) => {
return asingle.Firma.toLowerCase().indexOf(document.getElementById('Firma').value.toLowerCase()) !== -1;
}
);
var anzahl = filteredAdressen.length;
return (
<div>
<StateBox id="Firma" />
<StateBox id="PLZ" />
<li>
</li>
</div>
);
}
}
Input-field component:
import React, {Component} from 'react';
export default class StateBox extends Component {
//constructor input field
constructor() {
super();
//equal to object
this.state = {
search: ''
};
}
updateSearch(event) {
console.log(event.target.value);
this.setState({search: event.target.value});
}
render(){
return(
<form className="StateBox">
<input type="text" value={this.state.search} onChange={this.updateSearch.bind(this)}/>
</form>
);
}
}
You can declare the state in the parent component and pass function to update that in child component
class Parent extends Component {
this.state = {
value: ''
}
changeValue = (value) => {
this.setState({value});
}
render() {
return <Child inputValue={this.state.value} changeValue={this.state.changeValue} />
}
}
class Child extends Component {
render() {
<input value={this.props.inputValue} onChange={(e) => this.props.changeValue(e.target.value)} />
}
}
If you want to access the value of a child component, you need to lift the state up and make the child component controlled, because that's the way you should code in react.
Taking your code as base:
class AdressenListe extends Component {
constructor() {
super();
this.state = {
Firma: ''
};
}
changeValue (Firma) {
this.setState({Firma});
}
render() {
let filteredAdressen = this.props.adressen.filter(
(asingle) => {
return asingle.Firma.toLowerCase().indexOf(this.state.Firma.toLowerCase()) !== -1;
}
);
return (
<div>
<StateBox inputValue={this.state.Firma} changeValue={this.changeValue.bind(this)} />
</div>
);
}
}
Note how I pass down the necessary props and the state is managed by the parent.
class StateBox extends Component {
render () {
return <input type="text" value={this.props.inputValue} onChange={(e) => this.props.changeValue(e.target.value)} />
}
}
I want to call child function from parent component so I found a question here
Call child method from parent
So I used this way to to called it (From 1st Answer and 2nd approach).
Now issue is how to set state in the child getAlert function
class Parent extends Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends Component {
constructor(){
super();
this.state = {message:""};
}
getAlert() {
alert('clicked');
//HERE I NEED TO SETSTATE
}
render() {
return (
{this.state.message!=""?(
<h1>{this.state.message}</h1>
):(
<h1>Hello</h1>
)}
);
}
}
In the getAlert function of child I need to setState but I couldn't able to do it. Please provide any solution
The problem seems to be that when calling setState inside the getAlert function of child, this.setState will come undefined. This happens because this inside your getAlert function doesn't refer to the context of the React Component and setState is defined for the Component. You can solve this by binding the getAlert function.
You can do it in two ways.
First: using .bind(this) in constructor
class Child extends Component {
constructor() {
super();
this.getAlert = this.getAlert.bind(this);
}
getAlert() {
alert('clicked');
//HERE I NEED TO SETSTATE
}
render() {
return (
<h1>Hello</h1>
);
}
}
Second: use Arrow function
getAlert = () => {
alert('clicked');
//HERE I NEED TO SETSTATE
}
Check this answer on Why do we need to bind React functions
Check the working snippet
class Parent extends React.Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends React.Component {
constructor(){
super();
this.state = {message:""};
}
getAlert = () => {
alert('clicked');
this.setState({message: "somemessage"});
}
render() {
return (
<div>{this.state.message!=""?(
<h1>{this.state.message}</h1>
):(
<h1>Hello</h1>
)}</div>
);
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'))
<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="app"/>
class Parent extends React.Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends React.Component {
constructor(){
super()
this.state = {
message: 'google'
}
this.getAlert = this.getAlert.bind(this)
}
getAlert() {
alert('clicked');
this.setState ({
message: 'yahoo'
}, () => {
console.log(this.state.message) //the state value will be printed
});
}
render() {
console.log(this.state.message)
return (
<h1>Hello {this.state.message}</h1>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('container')
);
<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="container"></div>
you have bind the getAlert() method to scope of the class ie). 'this'. I have added an sample code..pls check
Let say I have two components called A and B.
B has a status which keeps changing and I would like to pass the status to A so that I can trigger event when certain condition is met.
How do I keep monitoring/getting state of child from another component in React?
Thanks!
When component on the same level:
class Parent extends React.Component {
constructor() {
super();
this.state = {
status: "B not clicked"
}
this.componentBchangeHandler = this.componentBchangeHandler.bind(this);
}
componentBchangeHandler(value) {
this.setState({ status: value })
}
render() {
return (
<div>
<ComponentA status={this.state.status} />
<ComponentB componentBchangeHandler={this.componentBchangeHandler} />
</div>
)
}
}
const ComponentA = (props) => <div>{props.status}</div>;
const ComponentB = (props) => <div onClick={() => props.componentBchangeHandler("some val")}>click me</div>;
https://codesandbox.io/s/k29mn21pov
And check out the documents I mentioned earlier.
If you're talking about a parent-child relationship, all you'd have to do is define a function that changes state on A and pass it as prop to B, like so:
class A extends Component {
constructor(props) {
super(props);
this.state = {
changed: false,
}
}
_statusChange = () => this.setState({ changed: !this.state.changed });
render() {
return(
<div>
<span>State on A: { this.state.changed.toString() }</span>
<B changeHandler={this._statusChange} />
</div>
)
}
}
class B extends Component {
render() {
return(
<div>
<button onClick={this.props.changeHandler}>Click me</button>
</div>
)
}
}
const App = () => (
<A />
);
If they should be on the same level, by convention, you should define a third component, wrap A and B in it, again passing state as props between them.