我们知道componentDidMount会在render函数执行之后即组件渲染之后执行。那么需要去后台准备数据的时候比如说获取list列表时,会在componentDidMount中去后台请求数据,然后更新到表单中。
但是在做react项目时,碰到配置项的模块(只有一个配置页面,没有list页面以及增删页面),会出现问题。
配置项一般会去检查输入的合法与否,所以我们一般会采用antd的form表单去做。需要通过this.state.item去绑定初始值,当页面渲染之后,调用componentDidMount时,请求返回数据再去更新数据就会出现数据更新不了的情况。
所以一般碰到这种问题,我们都会使用一个标志位来控制render函数的渲染,只有当componentDidMount中的请求返回时,我们才去设置标志位,去渲染form表单这就跟初始化一样。
比如:
在项目初始化的时候,我会在页面设置一些默认值
constructor(props) {
super(props);
this.state = {
periodUnit: "Hour(s)",
rememberDevice: true,
expireFlag: 0,
deviceValidityPeriod: 30,
maxDeviceNumberPerAccount: 5,
deviceMin: 1,
deviceMax: 365,
maxDeviceNumberPerAccountMin: 1,
maxDeviceNumberPerAccountMax: 10,
periodUnitArry: ["Day(s)", "Hour(s)", "Minute(s)"],
loadding: false
}
}
我们知道,constructor是在组件生成的时候首先回去执行的函数,它肯定是在render之前,这么设置数据显示也是没有问题的。
<Form {...formItemLayout} labelAlign="right">
<Collapse accordion expandIconPosition="right" defaultActiveKey={['2']} className="samp_collapse_style">
<Panel header={intl.get("samp.byodManagement.byodGlobalConfiguration.panel.registrationStrategy")} key="2" className="samp_collapse_panel_header">
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.periodUnit")} validateStatus={periodUnitError ? 'error' : ''} help={periodUnitError || ''}>
{getFieldDecorator('periodUnit', { initialValue: this.state.periodUnit, rules: rules.periodUnit })(
<Select
onChange={this.changePeriodUnit}
placeholder={intl.get("samp.common.pleaseSelect")}
>
{
this.state.periodUnitArry && this.state.periodUnitArry.map((item) => {
return <Option value={item} key={item}>{item}</Option>
})
}
</Select>)}
</Form.Item>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.rememberDevice")} validateStatus={rememberDeviceError ? 'error' : ''} help={rememberDeviceError || ''}>
{getFieldDecorator('rememberDevice', { initialValue: this.state.rememberDevice, rules: rules.rememberDevice })(
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" defaultChecked onChange={this.changeRememberDevice} />
)}
</Form.Item>
{
this.state.rememberDevice ?
<div>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.expireFlag")} hasFeedback validateStatus={expireFlagError ? 'error' : ''} help={expireFlagError || ''}>
{getFieldDecorator('expireFlag', { initialValue: this.state.expireFlag, rules: rules.expireFlag })(
<Radio.Group style={{ float: "left" }} onChange={this.changeExpireFlag}>
<Radio value={-1}>{intl.get("samp.byodManagement.byodGlobalConfiguration.item.neverExpire")}</Radio>
<Radio value={0}>{intl.get("samp.byodManagement.byodGlobalConfiguration.item.customization")}</Radio>
</Radio.Group>
)}
</Form.Item>
{
this.state.expireFlag === 0 ?
<div>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.deviceValidityPeriod")} hasFeedback validateStatus={deviceValidityPeriodError ? 'error' : ''} help={deviceValidityPeriodError || ''}>
{getFieldDecorator('deviceValidityPeriod', { initialValue: this.state.deviceValidityPeriod, rules: rules.deviceValidityPeriod })(
<InputNumber style={{ width: "100%" }} min={this.state.deviceMin} max={this.state.deviceMax} />
)}
</Form.Item>
<Form.Item label={
<span>
<Tooltip title={intl.get("samp.byodManagement.byodGlobalConfiguration.tips.maxDeviceNumberPerAccount")}>
<Icon type="question-circle-o" />
</Tooltip> {intl.get("samp.byodManagement.byodGlobalConfiguration.item.maxDeviceNumberPerAccount")}
</span>} hasFeedback validateStatus={maxDeviceNumberPerAccountError ? 'error' : ''} help={maxDeviceNumberPerAccountError || ''}>
{getFieldDecorator('maxDeviceNumberPerAccount', { initialValue: this.state.maxDeviceNumberPerAccount, rules: rules.maxDeviceNumberPerAccount })(
<InputNumber style={{ width: "100%" }} min={this.state.maxDeviceNumberPerAccountMin} max={this.state.maxDeviceNumberPerAccountMax} />
)}
</Form.Item>
</div> : ""
}
</div> : ""
}
</Panel>
</Collapse>
<div className="samp_panel_from_footer">
<div className="samp_panel_from_footer_button">
<Button type="primary" onClick={this.apply} htmlType="submit" disabled={hasErrors(getFieldsError())} disabled={hasErrors(getFieldsError())}>
{intl.get("samp.button.apply")}
</Button>
<Button type="primary" onClick={this.cancel} className="samp_panel_from_footer_button_cancle">{intl.get("samp.button.cancel")}</Button>
</div>
</div>
</Form>
这里通过initialValue去绑定state中的属性。
然后会在
componentDidMount() {
// 对于隐藏域的校验,目前还存在问题,先实现功能,后期优化打开初始化校验
this.props.form.validateFields();
this.getGlobalConfiguration()
}
获取配置之后会去setState属性
//获取global配置
getGlobalConfiguration = () => {
byodGlobalConfigurationService.getConfiguration().then((response) => {
console.log(response.data[0])
this.setState({
// periodUnit: response.data[0].periodUnit,
periodUnit: "Hour(s)",
expireFlag: response.data[0].expireFlag,
deviceValidityPeriod: response.data[0].deviceValidityPeriod,
maxDeviceNumberPerAccount: response.data[0].maxDeviceNumberPerAccount
})
response.data[0].rememberDevice === "Enabled" ? this.setState({ rememberDevice: true }) : this.setState({ rememberDevice: false })
})
}
其实设置时不会生效的。
那么怎么处理呢?
增加一个标志位loadding,初始值为false,那么在这里就不会去渲染form
{
this.state.loadding ?
<Form {...formItemLayout} labelAlign="right">
<Collapse accordion expandIconPosition="right" defaultActiveKey={['2']} className="samp_collapse_style">
<Panel header={intl.get("samp.byodManagement.byodGlobalConfiguration.panel.registrationStrategy")} key="2" className="samp_collapse_panel_header">
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.periodUnit")} validateStatus={periodUnitError ? 'error' : ''} help={periodUnitError || ''}>
{getFieldDecorator('periodUnit', { initialValue: this.state.periodUnit, rules: rules.periodUnit })(
<Select
onChange={this.changePeriodUnit}
placeholder={intl.get("samp.common.pleaseSelect")}
>
{
this.state.periodUnitArry && this.state.periodUnitArry.map((item) => {
return <Option value={item} key={item}>{item}</Option>
})
}
</Select>)}
</Form.Item>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.rememberDevice")} validateStatus={rememberDeviceError ? 'error' : ''} help={rememberDeviceError || ''}>
{getFieldDecorator('rememberDevice', { initialValue: this.state.rememberDevice, rules: rules.rememberDevice })(
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" defaultChecked onChange={this.changeRememberDevice} />
)}
</Form.Item>
{
this.state.rememberDevice ?
<div>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.expireFlag")} hasFeedback validateStatus={expireFlagError ? 'error' : ''} help={expireFlagError || ''}>
{getFieldDecorator('expireFlag', { initialValue: this.state.expireFlag, rules: rules.expireFlag })(
<Radio.Group style={{ float: "left" }} onChange={this.changeExpireFlag}>
<Radio value={-1}>{intl.get("samp.byodManagement.byodGlobalConfiguration.item.neverExpire")}</Radio>
<Radio value={0}>{intl.get("samp.byodManagement.byodGlobalConfiguration.item.customization")}</Radio>
</Radio.Group>
)}
</Form.Item>
{
this.state.expireFlag === 0 ?
<div>
<Form.Item label={intl.get("samp.byodManagement.byodGlobalConfiguration.item.deviceValidityPeriod")} hasFeedback validateStatus={deviceValidityPeriodError ? 'error' : ''} help={deviceValidityPeriodError || ''}>
{getFieldDecorator('deviceValidityPeriod', { initialValue: this.state.deviceValidityPeriod, rules: rules.deviceValidityPeriod })(
<InputNumber style={{ width: "100%" }} min={this.state.deviceMin} max={this.state.deviceMax} />
)}
</Form.Item>
<Form.Item label={
<span>
<Tooltip title={intl.get("samp.byodManagement.byodGlobalConfiguration.tips.maxDeviceNumberPerAccount")}>
<Icon type="question-circle-o" />
</Tooltip> {intl.get("samp.byodManagement.byodGlobalConfiguration.item.maxDeviceNumberPerAccount")}
</span>} hasFeedback validateStatus={maxDeviceNumberPerAccountError ? 'error' : ''} help={maxDeviceNumberPerAccountError || ''}>
{getFieldDecorator('maxDeviceNumberPerAccount', { initialValue: this.state.maxDeviceNumberPerAccount, rules: rules.maxDeviceNumberPerAccount })(
<InputNumber style={{ width: "100%" }} min={this.state.maxDeviceNumberPerAccountMin} max={this.state.maxDeviceNumberPerAccountMax} />
)}
</Form.Item>
</div> : ""
}
</div> : ""
}
</Panel>
</Collapse>
<div className="samp_panel_from_footer">
<div className="samp_panel_from_footer_button">
<Button type="primary" onClick={this.apply} htmlType="submit" disabled={hasErrors(getFieldsError())} disabled={hasErrors(getFieldsError())}>
{intl.get("samp.button.apply")}
</Button>
<Button type="primary" onClick={this.cancel} className="samp_panel_from_footer_button_cancle">{intl.get("samp.button.cancel")}</Button>
</div>
</div>
</Form> : ""
}
当请求数据回来的时候设置setState之后在将loadding值设置为true,由于state发生变化,回去重新渲染
//获取global配置
getGlobalConfiguration = () => {
this.setState({
loadding: false
})
byodGlobalConfigurationService.getConfiguration().then((response) => {
console.log(response.data[0])
this.setState({
// periodUnit: response.data[0].periodUnit,
periodUnit: "Hour(s)",
expireFlag: response.data[0].expireFlag,
deviceValidityPeriod: response.data[0].deviceValidityPeriod,
maxDeviceNumberPerAccount: response.data[0].maxDeviceNumberPerAccount
})
response.data[0].rememberDevice === "Enabled" ? this.setState({ rememberDevice: true }) : this.setState({ rememberDevice: false })
this.setState({
loadding: true
})
})
}
这样就可以显示设置之后的值