我有一个状态为task
的父组件,以及一个处理更改其名称的输入的子组件。输入使用自己的name
状态作为输入值。在submit
或blur
之后,将调用父函数来更新父task.name
的状态。在componentDidUpdate()
上的父级中,是通过websocket发送到服务器的新状态,服务器将更改发送到另一个客户端。
我的组件保留值,因为它处于状态,但是在另一个客户端(刚刚从服务器接收到新值),它保持不变,因为仅在componentDidMount()
中设置了输入值。 如何强制这些子组件处于新状态?
父母
componentDidMount() {
//Recieve changed data from server. This updates the state of all tasks, but doesn't invoke change of Child component because value has been set only in componentDidMount()
ioClient.on("onDataChanged", (data) => {
this.setState({tasks: data.tasks});
});
}
componentDidUpdate() {
//Sends data to server and invokes change in another clients
ioClient.emit('onDataChanged',this.state);
}
onTaskUpdate(task) {
const updatedTasks = this.state.tasks;
updatedTasks[task.id] = task;
const newState = {...this.state, tasks: updatedTasks};
this.setState(newState);
}
render() {
return (
{/* ... some code and for cycle of this.state.tasks */}
<Task key={task.id}
task={task}
onTaskUpdate={this.onTaskUpdate}
/>
{/* ... */}
);
}
孩子(任务)
constructor(props) {
super(props);
this.state = {name: ''};
this.handleInputChange = this.handleInputChange.bind(this);
this.nameFormSubmit = this.nameFormSubmit.bind(this);
}
componentDidMount() {
// component is already mounted so parents change doesn't invoke this again
this.setState({name: this.props.task.name});
}
handleInputChange(e) {
this.setState({[e.target.name]: e.target.value});
}
nameFormSubmit(e) {
e.preventDefault();
let updatedTask = {...this.props.task, name: this.state.name};
this.props.onUpdate(updatedTask);
}
render() {
return (
<form onSubmit={(e) => this.nameFormSubmit(e)}>
<input type="text"
name="name"
value={this.state.name}
onChange={this.handleInputChange}
/>
</form>
);
}
我正在使用组件自己的状态,因为我不想将每个按下的键发送给服务器,而只是发送给输入的最终状态。 预期结果:仅在提交时发送/发送更改的输入名称,而不是每次更改
答案 0 :(得分:0)
我当前的解决方案有效,但是我不满意,因为我认为解决方法不正确。
我使用了getDerivedStateFromProps
和新状态focused
来指示是否必须替换状态。切换focused
状态onFocus
和onBlur
。
以下更新的子组件:
孩子(任务)
constructor(props) {
super(props);
this.state = {
name: '',
focused: false
};
this.toggleFocusedState = this.toggleFocusedState.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.nameFormSubmit = this.nameFormSubmit.bind(this);
}
static getDerivedStateFromProps(props, state) {
return !state.focused ? {name: props.task.name} : null;
}
toggleFocusedState(state) {
this.setState({focused:state});
}
componentDidMount() {
this.setState({name: this.props.task.name});
}
handleInputChange(e) {
this.setState({[e.target.name]: e.target.value});
}
nameFormSubmit(e) {
e.preventDefault();
let updatedTask = {...this.props.task, name: this.state.name};
this.props.onUpdate(updatedTask);
}
render() {
return (
<form onSubmit={(e) => this.nameFormSubmit(e)}>
<input type="text"
name="name"
value={this.state.name}
onChange={this.handleInputChange}
onFocus={()=>this.toggleFocusedState(true)}
onBlur={()=>this.toggleFocusedState(false)}
/>
</form>
);
}