Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React.js通过单亲在不同的子级之间传递道具_Javascript_Reactjs_Ecmascript 6 - Fatal编程技术网

Javascript React.js通过单亲在不同的子级之间传递道具

Javascript React.js通过单亲在不同的子级之间传递道具,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我有一个前端控制台,我正试图在react中创建它,它使用一个侧菜单来过滤动态生成表中显示的数据库中的结果 组件的层次结构如下所示: App.js | |--SideMenu.js |--ResultsTable.js 因此,我了解到父级可以访问子组件中的道具,并且还可以将道具传递给其子级。我想做的是让侧菜单通过父App.js与结果表对话,除非有办法让孩子们直接交流?并相应地更新表,但是我遇到了一个奇怪的问题。当我点击SideMenu.js中的filter或reset按钮时,结果表组件中拾取的道

我有一个前端控制台,我正试图在react中创建它,它使用一个侧菜单来过滤动态生成表中显示的数据库中的结果

组件的层次结构如下所示:

App.js
|
|--SideMenu.js
|--ResultsTable.js
因此,我了解到父级可以访问子组件中的道具,并且还可以将道具传递给其子级。我想做的是让侧菜单通过父App.js与结果表对话,除非有办法让孩子们直接交流?并相应地更新表,但是我遇到了一个奇怪的问题。当我点击SideMenu.js中的filter或reset按钮时,结果表组件中拾取的道具会延迟,这需要我在注册前点击按钮2或3次。我相信解决办法很简单,但到目前为止我还没有找到。我认为当App.js将新的道具传递回ResultTable.js时会出现问题,但我不完全确定如何修复它

这是我的SideMenu.js代码

export default class SideMenu extends React.Component{

    constructor(){
        super();

        this.state={

            serviceParam: '',
            filterParam: '',
            services: [],
        }

        this.handleServiceChoice = this.handleServiceChoice.bind(this);
        this.handleSearch = this.handleSearch.bind(this);
        this.getServices = this.getServices.bind(this);
        this.handleReset = this.handleReset.bind(this);

    }

    componentWillMount(){

        this.getServices();
    }

    getServices(){
        const _this =this;
        let servicesData;

        let url = "http://mydevsite.ie/cgi-bin/log-queries/api/services";

        fetch(url)
            .then((resp) => resp.json())
            .then(function(data){

                servicesData = data;

                console.log("servicesData");
                console.log(servicesData);

                _this.setState({
                    services: servicesData
                });
            });
    }

    handleReset(){
        this.setState({
            serviceParam: null,
            filterParam: null,
        });

        let dropdownArrow = document.createElement("i");
        dropdownArrow.setAttribute("class", "material-icons right");
        dropdownArrow.innerHTML = "keyboard_arrow_down";
        document.getElementById("serviceDisplay").innerHTML = "Services";
        document.getElementById("serviceDisplay").appendChild(dropdownArrow);

        this.props.filterCallback(this.state.serviceParam);
    }

    handleSearch(){


        if(document.getElementById('search').value && this.state.serviceParam){
            let filterParam = "&search="+document.getElementById('search').value;
            console.log('In child - search 1');
            console.log(filterParam);

            let parentProps;
            parentProps= this.state.serviceParam+filterParam;
            this.props.filterCallback(parentProps);
        } else if (document.getElementById('search').value){
            let filterParam = "?search="+document.getElementById('search').value;
            console.log('In child - search 2');
            console.log(filterParam);

            let parentProps;
            parentProps=filterParam;
            this.props.filterCallback(parentProps);
        } else{
            let filterParam = this.state.serviceParam;
            console.log('In child - search 3');
            console.log(filterParam);

            let parentProps;
            parentProps=filterParam;
            this.props.filterCallback(parentProps);
        }



    }

    handleServiceChoice(e){
        console.log('sidebar target id');
        console.log(e.target.id);

        let serviceParam;
        let dropdownArrow = document.createElement("i");
        dropdownArrow.setAttribute("class", "material-icons right");
        dropdownArrow.innerHTML = "keyboard_arrow_down";
        document.getElementById("serviceDisplay").innerHTML = e.target.id;
        document.getElementById("serviceDisplay").appendChild(dropdownArrow);

        serviceParam = '?service='+e.target.id ;

        this.setState({
            serviceParam: serviceParam,
        });

    }

    render(){
        return(

            <ul className="side-nav fixed blue accent-1">
                <li className="logo"></li>

                <li>
                    <a id="serviceDisplay" href="#" className="dropdown-button waves-effect" data-activates="services">Services<i className="material-icons right">keyboard_arrow_down</i></a>

                        <ul id="services" className="dropdown-content">
                            {this.state.services.map((dropdown)=>{
                                return(
                                    <li key={dropdown.service}>
                                        <a id={dropdown.service} href="#" className="waves-effect" onClick={this.handleServiceChoice}>{dropdown.service}</a>
                                    </li>
                                );
                            })}                 
                        </ul>

                </li>

                <li className="bold"><a href="#">Supplier ID Search</a></li>
                <li className="search">
                    <div className="container center-align">
                        <input id="search" type="text" placeholder="Enter ID here" className="validate blue accent-2"></input>

                        <button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleSearch}>
                            Filter
                            <i className="material-icons right">search</i>
                        </button>
                    </div>
                </li>
                <li >
                    <div className="container center-align">
                        <button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleReset}>
                            Reset Logs
                            <i className="material-icons right">autorenew</i>
                        </button>
                    </div>
                </li>


            </ul>
        );



    };
}
以及ResultsTable.js:

export default class ResultsTable extends React.Component{

    constructor(){
        super();
        this.state = {
            logs: [],
            xml: '',
            render_xml: false,
        }

        this.ResultsTable = this.ResultsTable.bind(this);
        this.handleRequestXML = this.handleRequestXML.bind(this);
        this.handleResponseXML = this.handleResponseXML.bind(this);
        this.returnToLogs = this.returnToLogs.bind(this);
        this.renderTable = this.renderTable.bind(this);
        this.renderXml = this.renderXml.bind(this);
    }

    componentWillMount(){
        console.log('Child - In componentWillMount!');
        this.ResultsTable();

    }

    componentWillReceiveProps(){
        console.log('Child - In componentWillReceiveProps!');
        console.log(this.props.filter);

        this.ResultsTable();
    }

    returnToLogs(){
        this.setState({
            render_xml:false
        });
    }

    handleResponseXML(e){
        const _this =this;

        _this.setState({
            render_xml: true,
        });

        let id_param = '?_id='+e.target.id+'&type=response';
        let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param;
        fetch(url)
            .then((resp) => resp.json())
            .then(function(data){

                let xml = data;

                console.log("xml");
                console.log(xml);

                _this.setState({
                    xml: xml,
                });

            });
    }

    handleRequestXML(e){
        const _this =this;

        _this.setState({
            render_xml: true,
        });


        let id_param = '?_id='+e.target.id+'&type=request';
        let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param;
        fetch(url)
            .then((resp) => resp.json())
            .then(function(data){

                let xml = data;

                console.log("xml");
                console.log(xml);

                _this.setState({
                    xml: xml,
                });
            });
    }

    ResultsTable(){
        console.log('Child - In ResultsTable!');
        console.log(this.props.filter);

        const _this =this;
        let logData;

        let url = "http://mydevsite.ie/cgi-bin/log-queries/api/logs";



        if(this.props.filter){
            console.log('Child - Service Choice!');
            console.log(this.props.filter);
            url +=this.props.filter;
        }

        fetch(url)
            .then((resp) => resp.json())
            .then(function(data){

                logData = data;

                console.log("logData");
                console.log(logData);

                _this.setState({
                    logs: logData
                });
            });

    }



    renderTable(){
        console.log('In renderTable!');
        return (

            <table className="highlight">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Created</th>
                        <th>Last Changed</th>
                        <th>Service</th>
                        <th>Supplier Identifier</th>
                        <th>Request XML</th>
                        <th>Response XML</th>
                    </tr>

                </thead>
                <tbody>
                {this.state.logs.map((log)=>{
                    return(
                        <tr key={log._id}>
                            <td>{log._id}</td>
                            <td>{log.created}</td>
                            <td>{log.last_changed}</td>
                            <td>{log.service}</td>
                            <td>{log.supplier_identifier}</td>
                            <td><a id={log._id} onClick={this.handleRequestXML} href='#'>Click for XML</a></td>
                            <td><a id={log._id} onClick={this.handleResponseXML} href='#'>Click for XML</a></td>
                        </tr>
                    );
                })}

                </tbody>


            </table>


        );
    }

    renderXml(){
        console.log("In renderXml");
        return(
            <div className="card-panel">
                {this.state.xml}
                <hr/>
                <a className="waves-effect btn blue accent-2" onClick={this.returnToLogs}>Back to logs</a>
            </div>

        );
    }

    render(){
        if(this.state.render_xml){
            return this.renderXml();
        } else {
            return this.renderTable();
        }
    }
}
下面是父App.js组件

export default class App extends React.Component{

    constructor(){
        super();
        this.state = {
            filter: null,
        }

        this.handleFilterParam = this.handleFilterParam.bind(this);
    }

    handleFilterParam(filter){
        console.log('In parent - handleSearchParam');
        console.log(filter);
        this.setState({
            filter: filter
        });
    }

    render(){
        console.log('In parent - render');
        console.log(this.state.filter);

        return (
            <div className="row">

                <div className="col s4 l3">
                    <SideMenu 
                        filterCallback={this.handleFilterParam}
                    />
                </div>
                <div className="col s12 l9">
                    <Header />
                    <ResultsTable filter={this.state.filter}/>
                </div>

            </div>

        );
    }
}

我还是个新手,ES6因此,如果其中一些问题看起来很业余,我会提前道歉。

我找到了一个非常简单的解决方案,以防有人想知道和看到这个问题。我以前使用过这种生命周期方法,但直到现在才完全理解它

因此,在我的ResultsTable组件中,我添加了以下代码以“侦听”新道具并相应更新:

componentWillReceiveProps(nextProps) {
        if(this.props != nextProps) {
            this.props = nextProps;
            this.handleResultsTable();
        }
    }

只需将一些回调作为道具传递给组件,组件将在应用程序组件中执行代码,然后重新播放另一个组件,我相信这就是他已经在做的事情。OP,我看到您正在使用componentWillReceiveProps根据过滤器更改来更新结果,但我假设您需要使用componentWillUpdate,它将接收新的props。现在,每当过滤器发生更改时,您都在使用旧的props@Angels我很确定这就是我现在正在做的。我在侧菜单中有一个回调,然后触发App.js将新的道具传递回ResultsTable,但它似乎没有在第一次单击按钮时将其拾取并重新播放。这就是你的意思吗?@Sander我仍在思考react的生命周期功能,但我会尝试切换到componentWillUpdate,看看这是否会有所不同。如果我记得的话,我可能在某一点上使用过该函数,但出于某种原因,它每隔几秒钟就会启动一次,但我会看看它是如何运行的;它不会将null传递给应用程序,状态尚未更新,只需明确传递null即可。