React.js:如何从子级更新父级状态

时间:2018-09-08 10:31:47

标签: javascript reactjs react-native

我试图通过setState通过子组件更新父组件的状态。下面是我的父组件:

布局

import React from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import Header from '../components/header/header.jsx';
import Customizer from '../components/customizer/customizer';
import { Navbar, NavbarBrand, Collapse } from 'reactstrap';
export const settings = {
    navbarbg: 'skin1', 
    sidebarbg: 'skin6', 
    logobg: 'skin6' 
}
class Fulllayout extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            settings: settings
        };
    }
    render() {
        return (
             <div id="main-wrapper">
                <header data-navbarbg={this.state.settings.navbarbg}>
                    <Navbar expand="md" className={}></Navbar>
                </header>
                <div className="page-wrapper d-block"></div>
                <Customizer />
             </div>
        );
    }
}
export default Fulllayout;
在父级中,

我定义了一个导出的常量设置。在this.state中也给出了它。标题中有一个属性data-navbarbg={this.state.settings.navbarbg}

我想动态更改其值。因此,我有一个定制器,它作为孩子在父级中导入。以下是子组件:

定制程序

import React from 'react';
import { settings } from '../../layouts/fulllayout';
import update from 'immutability-helper';

class Customizer extends React.Component {
    constructor(props) {
        super(props);
        this.navbarbgChange = this.navbarbgChange.bind(this);
        this.state = {
            settings: settings
        };
    }
    navbarbgChange(e) {
        var skin = e.currentTarget.dataset.navbarbg;
        var abc = update(this.state.settings, {
            navbarbg: { $set: skin }
        });
        this.setState({ settings: abc });
    }

    render() {
        return (
            <aside className="customizer" id="customizer">
                <a className="service-panel-toggle text-white"></a>
                <div className="customizer-body pt-3">
                    <div className="mt-3 border-bottom px-3">
                        <ul className="theme-color mb-2">
                            <li><a data-navbarbg="skin1" onClick={this.navbarbgChange}></a></li>    
                        </ul>
                    </div>
                </div>
            </aside>
        );
    }
}
export default Customizer;

从定制工具中,通过单击颜色,我希望setState的父对象为data-navbarbg属性中给定的值。

如果我将此代码放在父jsx文件中,则可以正常工作,但出于某些原因,应将此文件分开存放。

那么,我的代码中缺少什么?还是整个方法是错误的?谢谢。

4 个答案:

答案 0 :(得分:1)

是否有理由在navbarbgChange中定义Customizer

您可以考虑将navbarbgChange移至Fulllayout

这样您就可以

<li><a data-navbarbg="skin1" onClick={this.props.navbarbgChange}></a></li>

这将确保Fulllayout的背景处于更新状态。由于settings是在父组件而不是子组件中定义的,因此这也确保了关注点之间的良好分离

答案 1 :(得分:1)

在react中,您始终可以将方法从父级传递到子级。让我们在父级中编写方法,以像这样从子级更改父级的状态。

class Fulllayout extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            settings: settings
        };
    }

    // This will be passed to the child component

    changeForCustomizerState() {
        this.setState({
            settings: abc
        });
    }

    changeForHeaderState() {
        this.setState({
            settings: abc
        });
    }

    render() {
        return (
             <div id="main-wrapper">
                <header chageNavbarbg={this.changeForHeaderState}>
                    <Navbar expand="md" className={}></Navbar>
                </header>
                <div className="page-wrapper d-block"></div>
                <Customizer chageNavbarbg={this.changeForCustomizerState} />
             </div>
        );
    }
}

然后,子级对象上的onClick只需从父级对象传递的子级对象中调用父级方法。

render() {
        return (
            <aside className="customizer" id="customizer">
                <a className="service-panel-toggle text-white"></a>
                <div className="customizer-body pt-3">
                    <div className="mt-3 border-bottom px-3">
                        <ul className="theme-color mb-2">
                            <li><a data-navbarbg="skin1" onClick={this.props.chageNavbarbg}></a></li>    
                        </ul>
                    </div>
                </div>
            </aside>
        );
    }

答案 2 :(得分:1)

状态更新可以使用回调在“父级从子级”中完成。检查下面的代码以更好地理解

布局:

 updateState = (skin) => {
     this.setState({
          settings.navbarbg: skin
     });
}

render(){
   return(
      <div>
         <Customizer updateState={this.updateState}
      </div>
   );
}

在您的定制器中

  navbarbgChange(e){
    const skin = e.currentTarget.dataset.navbarbg;
    this.props.updateState(skin);
}

OR

布局:

 updateState = (e) => {
     const skin = e.currentTarget.dataset.navbarbg;
     this.setState({
          settings.navbarbg: skin
     });
}

render(){
   return(
      <div>
         <Customizer updateState={this.updateState}
      </div>
   );
}

Customizer:直接将父函数传递给onClick

  <li><a data-navbarbg="skin1" onClick={this.props.updateState}></a></li>

也停止使用var,并主要开始使用let和const。 ECMASCRIPT本身主张避免使用var,因为它的窗口范围。

答案 3 :(得分:-1)

您可以从孩子处呼叫父母的navbarbgChange(e)

在父母中:

navbarbgChange(e) {
    var skin = e.currentTarget.dataset.navbarbg;
    var abc = update(this.state.settings, {
        navbarbg: { $set: skin }
    });
    this.setState({ settings: abc });
}

<Child parentNavbarbgChange={navbarbgChange} />

navbarbgChange的子通话中:

this.props.parentNavbarbgChange(e);
相关问题