简体   繁体   中英

React access state from another component

I'm learning React and I'm building a reports page. I create a ReportForm component with the search options for the reports and I'm including this ReportForm in my Reports component.

I'm trying to get the state from ReportForm.js in Reports.js

ReportForm.js:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import DateRangePicker from 'react-bootstrap-daterangepicker';
import * as action from '../store/actions/index';

class ReportForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            startDate: new Date(),
            endDate: new Date(),
            reports: []
        };
    }

    componentDidMount = async () => {
        await this.props.onLoadReport();
        this.setState({ reports: this.props.reports });
    }

    handleSelect = (start, end, label) => {
        this.setState({
            startDate: start._d,
            endDate: end._d
        });
    }

    getDateRanges = () => {
        const today = new Date();
        const first = today.getDate() - today.getDay();
        const last = first + 6;
        
        return {
            'Today': [today, today],
            'This Week': [
                new Date(today.setDate(first)),
                new Date(today.setDate(last))
            ],
            'This Month': [
                new Date(today.getFullYear(), today.getMonth(), 1),
                new Date(today.getFullYear(), today.getMonth()+1, 0)
            ],
            'This Year': [
                new Date(today.getFullYear(), 0, 1),
                new Date(today.getFullYear(), 11, 31)
            ]
        };
    }

    render() {
        const sDate = this.state.startDate.toLocaleDateString();
        const eDate = this.state.endDate.toLocaleDateString();
        const reports = this.state.reports;
        const initDates = {
            startDate: sDate,
            endDate: eDate,
            showDropdowns: true,
            ranges: this.getDateRanges()
        };
        return (
            <div className="row" style={{ marginBottom: "10px" }}>
                <div className="col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3">
                    <table className="table table-bordered">
                        <thead>
                            <tr>
                                <th className="text-center">Report</th>
                                <th className="text-center col-sm-4">Period</th>
                                <th className="text-center col-sm-3">Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td align="center">
                                    <select className="form-control" id="report">
                                        {reports.map((values, index) => {
                                            return (
                                                <option value={Object.keys(values)[0]}>{Object.values(values)[0]}</option>
                                            );
                                        })}
                                    </select>
                                </td>
                                <td align="center">
                                    <DateRangePicker
                                        initialSettings={initDates}
                                        onCallback={this.handleSelect}
                                    >
                                        <input type="text" className="form-control" />
                                    </DateRangePicker>
                                </td>
                                <td align="center"><button className="btn btn-success">Run Report</button></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        );
    }
};

const mapStateToProps = state => {
    return {
        reports: state.report.reports
    };
};

const mapDispatchToProps = dispatch => {
    return {
        onLoadReport: () => dispatch(action.getReports())
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(ReportForm);

Here is my Reports.js:

import React, { Component } from 'react';

import ReportForm from './ReportForm';

class Reports extends Component {

    render() {
        // How can I get state.startDate, state.endDate from ReportForm.js ?
       
        return (
            <div>
                <ReportForm />

                <div style={{display: 'flex', justifyContent: 'center'}}>
                    <h2>Content</h2>
                </div>
            </div>
        );
    }
};

export default Reports;

I would pass a onSubmit callback to ReportForm :

<ReportForm onSubmit={myCallback} />

Then I would call this callback with the state from the ReportForm component when the form is submitted.

Without knowing any other details about what you're doing, the typical way to share state is for it to be "owned" by the parent and passed into the child. So you might move the state you've defined here to Reports , then the data that is required by ReportForm can be passed in via that component's props (not state). If the child needs to perform operations determined by the parent, or change the data, it should also receive callback functions (in props) from the parent for doing that.

(Side note: since you say you are just learning React, it might be worth mentioning that the React devs encourage the use of "hooks" rather than classes for new React development. See https://reactjs.org/docs/hooks-intro.html )

import React, { Component } from 'react';

import ReportForm from './ReportForm';

class Reports extends Component {

constructor(props) {
    super(props);
    this.state = {};
    this.updateState = this.updateState.bind(this);
}

updateState(data){
     this.setState(data)
}


render() {
    // How can I get state.startDate, state.endDate from ReportForm.js ?
   
    return (
        <div>
            <ReportForm state={this.state} updateState={this.updateState}/>

            <div style={{display: 'flex', justifyContent: 'center'}}>
                <h2>Content</h2>
            </div>
        </div>
    );
}
};

export default Reports;

In the ReportForm Class Component's ComponentDidMout method call the updatState function like this:-

    componentDidMount = async () => {
        await this.props.onLoadReport();
        this.setState({ reports: this.props.reports });
        this.props.updateState(this.state);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM