我试图通过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文件中,则可以正常工作,但出于某些原因,应将此文件分开存放。
那么,我的代码中缺少什么?还是整个方法是错误的?谢谢。
答案 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);