[英]React. setState does not update state of subcomponents
This is my component-structure: ExchangeRateInput ExhangeRateValueInput ExhangeRateDialog 这是我的组件结构:ExchangeRateInput ExhangeRateValueInput ExhangeRateDialog
The state open in is passed through to ExhangeRateDialog as a prop. 打开状态作为道具传递给ExhangeRateDialog 。 But when i setState open to true in ExchangeRateInput it doesnt seem to change in ExhangeRateDialog .
但是当我在ExchangeRateInput中将setState打开为true时, ExhangeRateDialog中似乎没有更改。 Can someone please explain what i am doing wrong.
有人可以解释我在做什么错。
ExchangeRateInput ExchangeRateInput
import { composeWithTracker, composeAll } from 'react-komposer';
import React from 'react';
import useContext from '../../../containers/useContext.jsx';
import ExchangeRateValueInput from './ExchangeRateValueInput.jsx';
import ExchangeRateDialog from '../dialogs/ExchangeRateDialog.jsx';
const composer = (props, onData) => {
onData(null, {});
};
export class ExchangeRateInput extends React.Component { //Wrapper Component
constructor(props) {
super(props);
this.state = {
value: props.value || '',
date: '',
showDialog: props.showDialog || false,
};
this.onChange = this.onChange.bind(this);
}
onChange(event) {
const value = event.target.value;
this.setState({ value });
}
onOpenDialog() {
let bool = true;
this.setState({ showDialog: bool }, () => {
console.log(this.state);
});
}
render() {
return (
<div>
<ExchangeRateValueInput onChange={this.onChange} openDialog={this.onOpenDialog.bind(this)} value={this.state.value} />
<ExchangeRateDialog onChange={this.onChange} open={this.state.showDialog} />
</div>
);
}
}
ExchangeRateInput.propTypes = {
value: React.PropTypes.number,
onChange: React.PropTypes.func,
openExhangeRateDialog: React.PropTypes.func,
};
const ComposedExchangeRateInput = composeAll(
composeWithTracker(composer),
useContext()
)(ExchangeRateInput);
export default ExchangeRateInput;
ExchangeRateDialog ExchangeRateDialog
import React from 'react';
import FlatButton from 'material-ui/FlatButton';
import DatePicker from 'material-ui/DatePicker';
import Dialog from 'material-ui/Dialog';
import useContext from '../../../containers/useContext.jsx';
export class ExchangeRateDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
date: '',
open: props.open || false,
};
this.onDialogConfirm = this.onDialogConfirm.bind(this);
this.onDateChange = this.onDateChange.bind(this);
}
onDateChange(date) {
const value = this.getFakeExchangeRate(); // Replace functionallity with Meteor-method
setTimeout(() => {
this.setState({ date, value });
}, 1100);
}
onDialogConfirm() {
this.props.onDialogConfirm({
value: this.state.value,
date: this.state.date,
});
}
getFakeExchangeRate() {
return Math.random(1, 15);
}
actions() {
return [
<FlatButton
label="Cancel"
secondary
onTouchTap={this.props.onDialogCancel}
/>,
<FlatButton
label="Ok"
primary
onTouchTap={this.onDialogConfirm}
disabled={!this.state.value}
/>,
];
}
render() {
return (
<div >
<Dialog
title="Get exchange rate from Riksbanken"
modal={false}
open={this.state.open}
actions={this.actions()}
onRequestClose={this.props.onDialogCancel}
>
Choose a date.
<div className="layout horizontal">
<div className="flex">
<DatePicker
hintText="No date selected"
onChange={(event, date) => this.onDateChange(date)}
maxDate={new Date()}
/>
</div>
<div className="flex">
<h3>{this.state.value ? `Exchange rate: ${this.state.value}` : null}</h3>
</div>
</div>
</Dialog>
</div>
);
}
}
ExchangeRateDialog.propTypes = {
value: React.PropTypes.number,
date: React.PropTypes.string,
open: React.PropTypes.bool,
onChange: React.PropTypes.func,
onDialogCancel: React.PropTypes.func,
onDialogConfirm: React.PropTypes.func,
};
export default ExchangeRateDialog;
ExchangeRateValueInput ExchangeRateValueInput
import React from 'react';
import TextField from 'material-ui/TextField';
import IconButton from 'material-ui/IconButton';
import useContext from '../../../containers/useContext.jsx';
export class ExchangeRateValueInput extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value || '',
errorMessage: '',
};
this.onValueChange = this.onValueChange.bind(this);
}
onValueChange(event) {
const value = event.target.value;
let errorMessage = '';
let returnValue = value;
const isNumber = !isNaN(value); // TODO: Improve validation
if (!isNumber) {
errorMessage = 'Must be a number';
returnValue = '';
}
this.setState({
value,
errorMessage,
}, () => {
this.props.onChange(returnValue);
});
}
onOpenDialog() {
console.log('hej');
console.log(this.props);
this.props.onOpenDialog;
}
style = {
height: 72,
};
render() {
return (
<div className="layout horizontal" style={this.style}>
<div
className=""
>
<TextField
floatingLabelText="Value"
onChange={this.onValueChange}
errorText={this.state.errorMessage}
value={this.state.value}
/>
</div>
<div
className="layout center layout horizontal"
>
<IconButton
className="flex"
tooltip="Get from Riksbanken"
onClick={() => this.props.openDialog()}
>
<i className="material-icons">search</i>
</IconButton>
</div>
</div>
);
}
}
ExchangeRateValueInput.propTypes = {
value: React.PropTypes.number,
onChange: React.PropTypes.func,
openDialog: React.PropTypes.func,
};
export default ExchangeRateValueInput;
You're passing value
from ExchangeRateInput
to ExchangeRateValueInput
, but then you're storing it in the internal state of ExchangeRateValueInput
. 您要将
value
从ExchangeRateInput
传递到ExchangeRateValueInput
,但随后将其存储在ExchangeRateValueInput
的内部状态中。 At this point, its completely disconnected from ExchangeRateInput
. 此时,它已与
ExchangeRateInput
完全断开连接。 So, when ExchangeRateValueInput
updates its state, its parent knows nothing about it. 因此,当
ExchangeRateValueInput
更新其状态时,其父级对此一无所知。
You could rewrite things so that all state is managed in the root component ( ExchangeRateInput
) and it passes that state down to the children who only reference props, rather than their own internal state. 您可以重写内容,以便在根组件(
ExchangeRateInput
)中管理所有状态,并将该状态传递给仅引用道具而不是其内部状态的子级。 Then, when the children need to update state, they can call some event that you define (eg this.props.onChange
or something). 然后,当孩子需要更新状态时,他们可以调用您定义的某个事件(例如
this.props.onChange
东西)。 ExchangeRateInput
would handle those events, and update its state accordingly. ExchangeRateInput
将处理这些事件,并相应地更新其状态。
Alternatively, you need to look into using a flux pattern (eg using something like Redux). 或者,您需要研究使用磁通量模式(例如,使用Redux之类的东西)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.