我是React的新手,对不起我的英语。
当我将数据从Child传递到父组件并单击另一个按钮时,它不会呈现。
正如您在我的注释中所看到的,setState创建了一个无限循环,停止了更新值的选项。
我尝试了不同的方法来解决在this.name = ''
和this.selected = []
等内部构造变量中创建问题,并将回调设置为this.name = name
和this.selected = selected
但不渲染当我点击其他选项时。
我尝试使用componentDidMount()
和其他生命周期方法,但我不知道如何解决它。
App.js(父组件)
state = { name: '', selected: [] };
doParentControl = (name, selected) => {
console.log('doParentControl name: ',name);
console.log('doParentControl selected: ',selected);
// this.setState({ name: name, selected: selected }) --> infinite loop
}
render() {
console.log('-> render App')
return (
<div className="App">
<header className="App-header">
<h1>Map</h1>
</header>
<div className="Map">
<Navbar parentControl={this.doParentControl}/>
<MapComponent name={this.state.name} selected={this.state.selected}/>
</div>
<div className="clearfix" />
</div>
);
}
Navbar.js(子组件)
constructor(props) {
super(props);
this.selected = [false, false, false];
this.state = { name: 'tile' };
}
handleClick = (e) => {
this.setState({name: e.target.value});
}
handleChange = (e) => {
switch(e.target.value) {
case 'option1': {
this.setState({ selected: this.selected[0] = e.target.checked})
break;
}
case 'option2': {
this.setState({ selected: this.selected[1] = e.target.checked})
break;
}
case 'option3': {
this.setState({ selected: this.selected[2] = e.target.checked})
break;
}
default:
break;
}
}
doParentControlFromChild = () => {
this.props.parentControl(this.state.name, this.selected);
}
render() {
console.log('render Navbar ->')
return (
<div className="nav-bar">
<nav className="App-nav">
<div className="buttons">
<button name="tile" onClick={this.handleClick} value="tile">Tile</button>
<button name="tile-watercolor" onClick={this.handleClick} value="tile-watercolor">Tile WaterColor</button>
<button name="cartografia" onClick={this.handleClick} value="cartografia">Cartografía</button>
<button name="satelite" onClick={this.handleClick} value="satelite">Satélite</button>
<button name="mapa" onClick={this.handleClick} value="mapa">Mapa</button>
</div>
<div className="clearfix"></div>
</nav>
<div className="checkbox">
<label><input type="checkbox" name="option1" value="option1" onChange={this.handleChange} />Option 1</label>
<label><input type="checkbox" name="option2" value="option2" onChange={this.handleChange} />Option 2</label>
<label><input type="checkbox" name="option3" value="option3" onChange={this.handleChange} />Option 3</label>
</div>
<div className="clearfix" />
{ this.doParentControlFromChild() }
</div>
);
}
答案 0 :(得分:1)
{ this.doParentControlFromChild() }
正在对渲染进行函数调用,这会导致状态更改,从而导致重新渲染,从而导致循环。摆脱parens并且只允许从用户操作调用调用setState
的函数,而不仅仅是渲染调用。这样的事情会做:
<div className="clearfix" onClick={this.doParentControlFromChild}/>
答案 1 :(得分:1)
setState()
让render()
函数重新渲染
因此,setState()
部署在父组件中的doParentControl
会导致组件重新呈现,而在您的子组件中,return( ... { this.doParentControlFromChild()} ... )
只会伴随元素呈现。这会导致您的父组件doParentControl
再次被调用,所以这里我们有无限循环
就像之前的回答所说的那样,只有在需要发生时才需要调用doParentControlFromChild
。
App.js (Father)
...
state = { name: '', selected: [] };
doParentControl = (name, selected) => {
console.log('doParentControl name: ',name);
console.log('doParentControl selected: ',selected);
this.setState({ name: name, selected: selected })
}
render() {
console.log('-> render App')
return (
<div className="App">
<header className="App-header">
<h1>Map</h1>
</header>
<div className="Map">
<Navbar parentControl={this.doParentControl}/>
<MapComponent name={this.state.name} selected={this.state.selected}/>
</div>
<div className="clearfix" />
</div>
);
}
...
Navbar.js (Child)
...
constructor(props) {
super(props);
this.selected = [false, false, false];
this.state = { name: 'tile' };
}
handleClick = (e) => {
this.setState({name: e.target.value});
}
handleChange = (e) => {
let index = e.target.value.match(/\d/); // fetch the idx
this.setState({ selected: this.selected[index] = e.target.checked}, () => {
this.doParentControlFromChild()
})
}
doParentControlFromChild = () => {
this.props.parentControl(this.state.name, this.selected);
}
render() {
console.log('render Navbar ->')
return (
<div className="nav-bar">
<nav className="App-nav">
<div className="buttons">
<button name="tile" onClick={this.handleClick} value="tile">Tile</button>
<button name="tile-watercolor" onClick={this.handleClick} value="tile-watercolor">Tile WaterColor</button>
<button name="cartografia" onClick={this.handleClick} value="cartografia">Cartografía</button>
<button name="satelite" onClick={this.handleClick} value="satelite">Satélite</button>
<button name="mapa" onClick={this.handleClick} value="mapa">Mapa</button>
</div>
<div className="clearfix"></div>
</nav>
<div className="checkbox">
<label><input type="checkbox" name="option1" value="option1" onChange={this.handleChange} />Option 1</label>
<label><input type="checkbox" name="option2" value="option2" onChange={this.handleChange} />Option 2</label>
<label><input type="checkbox" name="option3" value="option3" onChange={this.handleChange} />Option 3</label>
</div>
<div className="clearfix" />
</div>
);
}