alingo alingo - 13 days ago 9
React JSX Question

How to setState for array immediately?

I ran into one problem connected with updating state in react.

Well, I have some data and I want to build a table with this data. But, I would like to filter it first. The filtration is working well, but I only have problem with updating filtered data and throwing it to the next component... (I know that setState is not working immediately...)

updatedReports in ReportTable component still has not filtered data...
What is the best way to fix it and to work with updating state for arrays.

export default class ReportContent extends React.Component {

constructor(props) {
super(props);
this.state = {
currentReports: this.props.reports
};
}

_filterBy(option) {
let updatedReports = [...this.props.reports].filter(report => {
if (report.organizations === option || report.reportType === option) {
return report;
}
});
console.log(updatedReports);
this.setState({currentReports: updatedReports});
}

render() {
return (
<div className="reports-table">
<ReportMenu organizations={this.props.organizations} reportTypes={this.props.reportTypes}
filterBy={this._filterBy.bind(this)}/>
<ReportTable updatedReports={this.state.currentReports}/>
</div>
);
}


}

Answer

There's nothing wrong with the code you provided. setState should work if invoked correctly. My bet is the problem is within your other components or the data.

Here's a snippet that uses your code. I have no idea how you implement your other components so I just made some assumptions here.

class ReportMenu extends React.Component {
    render() {
        return <div className="well well-default">
            <select className="form-control" onChange={(e) => {
                this.props.filterBy(e.target.value)
            }}>
                <option> - </option>
                {this.props.organizations.map(
                    (item, index) => <option key={index}>{item}</option>
                )}
            </select>
            <br/>
            <select className="form-control" onChange={(e) => {
                this.props.filterBy(e.target.value)
            }}>
                <option> - </option>
                {this.props.reportTypes.map(
                    (item, index) => <option key={index}>{item}</option>
                )}
            </select>
        </div>
    }
}

class ReportTable extends React.Component {
    render() {
        return <table className="table table-bordered">
            <tbody>
                {this.props.updatedReports.map(
                    (item, index) => <tr key={index}>
                        <td>{index}</td>
                        <td>{item.organizations}</td>
                        <td>{item.reportType}</td>
                    </tr>
                )}
            </tbody>
        </table>
    }
}

class ReportContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            currentReports: this.props.reports
        };
    }
    _filterBy(option) {
        let updatedReports = this.props.reports.filter(report => {
            if (report.organizations === option || report.reportType === option) {
                return report;
            }
        });
        console.log(updatedReports);
        this.setState({currentReports: updatedReports});
    }
    render() {
        return (
            <div className="reports-table">
                <ReportMenu 
                    organizations={this.props.organizations} 
                    reportTypes={this.props.reportTypes} 
                    filterBy={this._filterBy.bind(this)}/>
                <ReportTable updatedReports={this.state.currentReports}/>
            </div>
        );
    }
}

class App extends React.Component {
    render() {
        const reports = [
            {
                organizations: 'orgA',
                reportType: 'typeA'
            }, {
                organizations: 'orgA',
                reportType: 'typeB'
            }, {
                organizations: 'orgB',
                reportType: 'typeA'
            }, {
                organizations: 'orgB',
                reportType: 'typeB'
            }
        ];
        return <div className="container">
            <h1 className="page-header">Reports</h1>
            <ReportContent 
                reports={reports} 
                organizations={['orgA', 'orgB']} 
                reportTypes={['typeA', 'typeB']}/>
        </div>
    }
}

ReactDOM.render(<App/>, document.getElementById('root'));
Comments