React.js。有没有办法实现通用 "onChange" 事件处理程序
React.js. Is there way to implement universal "onChange" event handler
我对 React 的 setState 有点困惑。
我试图实现 changeHandler
方法来改变状态,但我遇到了一些问题。
我创建了 4 个文本字段,name
属性 表示 this.state.workerInfo.foo
的 属性,所以在 changeHandler
中我提取了 event.target.name
到 link 状态的新值。
class EditableWorkerProfile extends Component {
constructor(props) {
super(props);
this.state = {
pending: false,
shouldAdd: false,
worker_id: props.worker._id,
workerInfo: {
login: props.worker.login,
balance: props.worker.balance,
phoneNum: props.worker.phoneNum.replace(new RegExp("(^\+7)|(^8)"), "7"),
birthDate: props.worker.birthDate,
address: props.worker.address,
city: props.worker.city,
name: props.worker.name,
isDriver: props.worker.isDriver,
veh_is_open: this.props.worker.isDriver ? this.props.worker.veh_is_open : false,
veh_height: this.props.worker.isDriver ? this.props.worker.veh_height : "0",
veh_width: this.props.worker.isDriver ? this.props.worker.veh_width : "0",
veh_length: this.props.worker.isDriver ? this.props.worker.veh_length : "0",
veh_loadingCap: this.props.worker.isDriver ? this.props.worker.veh_loadingCap : "0",
veh_frameType: this.props.worker.isDriver ? this.props.worker.veh_frameType : "Открытый борт" ,
height: !this.props.worker.isDriver ? this.props.worker.height : "0",
weight: !this.props.worker.isDriver ? this.props.worker.weight : "0",
rating: props.worker.rating,
}
}
}
render() {
let { classes, worker } = this.props;
let { pending, shouldAdd, workerInfo, worker_id } = this.state;
return <Card>
<CardBody>
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Balance" name="balance" onChange={this.handleChange} />
</GridItem>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Login" name="login" onChange={this.handleChange} />
</GridItem>
<GridItem id='worker_phone' xs={6} sm={6} md={6}>
<TextField label="Phone number" name="phoneNum" onChange={this.handleChange} />
</GridItem>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Address" name="address" onChange={this.handleChange} />
</GridItem>
</GridContainer>
</GridContainer>
</CardBody>
</Card>
}
}
我已经实现了两种方法handleChange
,但它们似乎不太好。
第一种方法可行,但我认为复制状态不是一个好主意。
handleChange = (is_check = false) => (e) => {
let value = e.target[is_check ? "checked" : "value"]
this.updateState(e.target.name, value);
}
updateState = async (field, value) => {
//Slow method
field = 'workerInfo.'+field
let init_state = _.clone(this.state, true);
_.set(init_state, field, value);
await this.setState(init_state);
}
第二种方法根本行不通。
它会破坏 workerInfo
中的所有字段,只放置一个已更改的字段。
handleChange = () => async event => {
const name = event.target.name
await this.setState({workerInfo:{ [name]: event.target.value}})
});
};
使用之前的状态也会给出不正确的结果。
this.setState((prevState) => {
return {workerInfo: { ...prevState.workerInfo, [name]: event.target.value}}
});
那么实现通用 changeHandler
功能的方法是什么,它将更新状态,使用文本字段的 name
到 link 和 state.workerInfo
字段?
我能想到使用 prevState
这个简单的更改处理程序是这样的,
handleChange = (event) => {
const name = event.target.name
const value = event.target.value
this.setState(prevState => ({
workerInfo:{
...prevState.workerInfo,
[name]: value
}}
), ()=> console.log(this.state.workerInfo))
}
注:我觉得更新状态的时候没必要用async/await
。
我对 React 的 setState 有点困惑。
我试图实现 changeHandler
方法来改变状态,但我遇到了一些问题。
我创建了 4 个文本字段,name
属性 表示 this.state.workerInfo.foo
的 属性,所以在 changeHandler
中我提取了 event.target.name
到 link 状态的新值。
class EditableWorkerProfile extends Component {
constructor(props) {
super(props);
this.state = {
pending: false,
shouldAdd: false,
worker_id: props.worker._id,
workerInfo: {
login: props.worker.login,
balance: props.worker.balance,
phoneNum: props.worker.phoneNum.replace(new RegExp("(^\+7)|(^8)"), "7"),
birthDate: props.worker.birthDate,
address: props.worker.address,
city: props.worker.city,
name: props.worker.name,
isDriver: props.worker.isDriver,
veh_is_open: this.props.worker.isDriver ? this.props.worker.veh_is_open : false,
veh_height: this.props.worker.isDriver ? this.props.worker.veh_height : "0",
veh_width: this.props.worker.isDriver ? this.props.worker.veh_width : "0",
veh_length: this.props.worker.isDriver ? this.props.worker.veh_length : "0",
veh_loadingCap: this.props.worker.isDriver ? this.props.worker.veh_loadingCap : "0",
veh_frameType: this.props.worker.isDriver ? this.props.worker.veh_frameType : "Открытый борт" ,
height: !this.props.worker.isDriver ? this.props.worker.height : "0",
weight: !this.props.worker.isDriver ? this.props.worker.weight : "0",
rating: props.worker.rating,
}
}
}
render() {
let { classes, worker } = this.props;
let { pending, shouldAdd, workerInfo, worker_id } = this.state;
return <Card>
<CardBody>
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Balance" name="balance" onChange={this.handleChange} />
</GridItem>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Login" name="login" onChange={this.handleChange} />
</GridItem>
<GridItem id='worker_phone' xs={6} sm={6} md={6}>
<TextField label="Phone number" name="phoneNum" onChange={this.handleChange} />
</GridItem>
<GridItem xs={12} sm={12} md={12}>
<TextField label="Address" name="address" onChange={this.handleChange} />
</GridItem>
</GridContainer>
</GridContainer>
</CardBody>
</Card>
}
}
我已经实现了两种方法handleChange
,但它们似乎不太好。
第一种方法可行,但我认为复制状态不是一个好主意。
handleChange = (is_check = false) => (e) => {
let value = e.target[is_check ? "checked" : "value"]
this.updateState(e.target.name, value);
}
updateState = async (field, value) => {
//Slow method
field = 'workerInfo.'+field
let init_state = _.clone(this.state, true);
_.set(init_state, field, value);
await this.setState(init_state);
}
第二种方法根本行不通。
它会破坏 workerInfo
中的所有字段,只放置一个已更改的字段。
handleChange = () => async event => {
const name = event.target.name
await this.setState({workerInfo:{ [name]: event.target.value}})
});
};
使用之前的状态也会给出不正确的结果。
this.setState((prevState) => {
return {workerInfo: { ...prevState.workerInfo, [name]: event.target.value}}
});
那么实现通用 changeHandler
功能的方法是什么,它将更新状态,使用文本字段的 name
到 link 和 state.workerInfo
字段?
我能想到使用 prevState
这个简单的更改处理程序是这样的,
handleChange = (event) => {
const name = event.target.name
const value = event.target.value
this.setState(prevState => ({
workerInfo:{
...prevState.workerInfo,
[name]: value
}}
), ()=> console.log(this.state.workerInfo))
}
注:我觉得更新状态的时候没必要用async/await
。