Reputation: 1427
Help me please to get states of elements inside react component or other some custom features with information which I need. Every of td tags contains react component Block1. Simplified code structure below
class Block2 extends React.Component {
render() {
return (
<table>
<tbody>
<tr>
<td>
<Block1 />
</td>
<td>
<Block1 />
</td>
</tr>
</tbody>
</table>
)}}
Block1 - react component which contain div elements. Block2 is inside component Block3. How to get states of Block1 from Block3 by click on some button? Now, I can get list of Block1 and may see props, but I can't see states. Or I can get DOM td elements and see children classNames (which I looking for in states) but I can't see props...
Upvotes: 1
Views: 5726
Reputation: 9582
Unless you use libraries like Redux, you have to do the following to solve your problem:
Store the state inside Block3
and not Block1
. Then pass any function that changes this state as props
from Block3
to Block2
to Block1
. When any change occurs in Block1
, call this function. The pattern should be:
class Block3 {
changeState(value) {
this.setState({ stateValue: value });
}
render() {
return (
<Block2 changeState={this.changeState}/>
)
}
}
class Block2 extends React.Component {
render() {
return (
<table>
<tbody>
<tr>
<td>
<Block1 changeState={this.props.changeState} />
</td>
<td>
<Block1 changeState={this.props.changeState} />
</td>
</tr>
</tbody>
</table>
)}}
class Block1 {
changeHandler(ev) {
this.props.changeState(ev.target.value);
}
render() {
return (
<button onClick={this.changeHandler}/>
)
}
}
If you really want to access the child state
inside a parent component, consider using refs
:
class Block2 {
render() {
return <Block1 ref={ (childComponent) => { this.block1Child = childComponent; } } />;
// Now you may use this.block1Child to access child component's state eg: this.block1Child.setState({})
}
}
EDIT: My solution after seeing your code:
import React, { Component } from 'react';
import './Hall.css';
class HallCol extends Component {
constructor(props) {
super(props);
this.state = {
chair_cls:'chair-default'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
let chair_cls = null;
if(this.state.chair_cls==="chair-default") {
chair_cls = 'chair-sold';
this.props.updateCount(1, this.props.seat_number);
} else {
chair_cls = 'chair-default';
this.props.updateCount(-1, this.props.seat_number);
}
this.setState({
chair_cls: chair_cls
});
}
render(){
return(
<div className={this.state.chair_cls} onClick={this.handleClick}>
<div className="backrest">
<p>{this.props.seat_number}</p>
</div>
<div className="armrest-left">
</div>
<div className="armrest-right">
</div>
</div>
);
}
}
class Table extends React.Component {
constructor() {
super();
this.genRow = this.genRow.bind(this); // this is method binding
}
genRow() {
var rows = this.props.rows;
return rows.map(function(v, i) {
var tmp = v.map(function(v2, j) {
return (
<td key={'td' + i + '_' + j} className='chair-cell' >
{v2}
</td>
);
});
return (
<tr key={'tr' + i}>
{tmp}
</tr>
)
});
}
render() {
return (
<table className="hall-grid" >
<tbody>
{this.genRow()}
</tbody>
</table>
);
}
}
class Hall extends React.Component {
constructor(props) {
super(props);
var rows_num = this.props.rows;
var cols_num = this.props.cols;
this.AddRow = this.AddRow.bind(this);
this.updateSeats = this.updateSeats.bind(this);
var row = [];
for (var i = 0; i < rows_num; i++) {
var col = [];
for (var k = 0; k< cols_num; k++) {
col.push(<HallCol row = {i+1} seat_number = {k+1} updateCount={this.updateSeats} />); // bind the passed function to parent
}
row.push(col);
}
this.state = {
rows: row,
bookedSeats: [],
count: 0
};
}
AddRow() {
let newRows = this.state.rows;
newRows.push([0, 0]);
this.setState({rows: newRows});
}
updateSeats(val, seat_number) {
let bookedSeatsUpdated;
if( val === 1 ) {
bookedSeatsUpdated = this.state.bookedSeats.concat(seat_number);
} else {
bookedSeatsUpdated = this.state.bookedSeats;
let index = bookedSeatsUpdated.indexOf(seat_number);
bookedSeatsUpdated.splice(index,1);
}
this.setState({
bookedSeats: bookedSeatsUpdated,
count: this.state.count + val
});
}
render() {
return (
<div className="hall">
<Table rows={this.state.rows} />
<button className = "btn-default" onClick={() => {
alert(this.state.count + 'seats : ' + this.state.bookedSeats);
} }>
TOTAL SOLD
</button>
</div>
);
}
}
export default Hall;
Upvotes: 1