數棧技術文章分享:你竟然是這樣的initialValue

先說一下寫着篇文章的契機,是由於回顯,複雜表單的回顯,讓我以爲我對initialValue這個屬性是有誤解的。react

1、initialValue的出處和定義git

initialValue的出處:github

AntDesign/Form表單件/getFieldDecorator(id,options)裝飾器函數/第二個參數options/options.initialValue。antd

連接地址:https://ant.design/components...

關於屬性initialValue,官方的解釋以下:app

關鍵字是「子節點的初始值」,初始值也就是默認值,好比Form中有一個城市的選擇器,默認選擇「杭州」,那麼initialValue就是杭州對應的value。函數

因此其實我一直覺得initialValue是defaultValue同樣的存在。工具

2、initialValue和defaultValue的區別fetch

  1. defaultValue的例子

import React, { Component,Fragment } from 'react';
import { Button,Input } from "antd";
export default class CreateFrom extends Component {
state={value:"value"}
updateValue = () => {ui

this.setState({value:"newValue"})

}
render() {this

return (
  <Fragment>
    <Button onClick={this.updateValue}>更新value</Button>
    <Input defaultValue={this.state.value} />
  </Fragment>
);

}
}

說明:當該組件被渲染時,Input中的值爲」value「,當我點擊「更新value按鈕」時,Input中的值不更新。

Input組件沒有設置value屬性的話,就是一個非受控組件,它須要設置defaultValue,若是用戶不手動改變Input的輸入,那麼Input就一直顯示defaultValue指向的值(友情提示:值爲Input組件第一次被渲染時的真實值,變量或者常量指向的真實值)。這裏涉及到了受控組件和非受控組件的知識,不作延伸。

  1. intialValue的例子

1)models/list.js

let count = 1;
const CITY = ["杭州","北京","上海","廣州","深圳"];
export default {
namespace: 'list',

state: {

citys: CITY,
detail:{city:CITY[count%5],count}

},

effects: {

*fetchDetail({ payload }, { call, put }) {
  // 不發請求,而是直接更新reducer
  // const response = yield call(service, payload);
  count++; 
  yield put({
    type: 'queryDetail',
    payload: {city:CITY[count%5],count},
  });
},

},

reducers: {

queryDetail(state, action) {
  return {
    ...state,
    detail: action.payload,
  };
}

},
};

2)router組件文件

import React, { Component } from 'react';
import { connect } from "dva";
import { InputNumber,Select,Form,Button } from "antd";

const FormItem = Form.Item;
const { Option } = Select;
const formItemLayout = {
labelCol: {

xs: { span: 24 },
sm: { span: 2 },

},
wrapperCol: {

xs: { span: 24 },
sm: { span: 22 },

},
};
@connect(({list})=>({
citys:list.citys,
detail:list.detail
}))
class CreateFrom extends Component {
getDetail = () => {

this.props.dispatch({type:"list/fetchDetail"});

}
render() {

const { form,detail={},citys=[] } = this.props;
const { getFieldDecorator } = form;
const { city,count } = detail;
return (
  <Form>
    <Button onClick={this.getDetail}>從新獲取數據</Button>
    <FormItem
      {...formItemLayout}
      label="城市"
    >
      {getFieldDecorator('city', {
        initialValue: city,
        rules: [{ required: true, message: '請選擇城市' }],
      })(
        <Select style={{width:160}} placeholder="請選擇城市">
        {
          citys.map(item=><Option key={item} value={item}>{item}</Option>)
        }
        </Select>
      )}
    </FormItem>
    <FormItem
      {...formItemLayout}
      label="總量"
    >
      {getFieldDecorator('count', {
        initialValue:count,
        rules: [{ required: true, message: '總量(1-99999999)',pattern:/^[1-9][0-9]{0,7}$/ }],
      })(
        <InputNumber style={{width:160}}/>
      )}
    </FormItem>
  </Form>
);

}
}

export default Form.create()(CreateFrom);

說明:當該Form組件被渲染時,接收props.detail,由於在models/list.js文件的state中已經初始化,因此,第一次render被渲染的值是「杭州」和「1」,點擊「從新獲取數據按鈕」,這個時候props.detail改變爲{city:"北京",count:2},與此同時Form被渲染的值也隨之改變。

uhmmm,怎麼和defaultValue的表現方式不同?不是說好是默認值的嘛?不是說好不會跟着數據的改變而改變的嘛?逗我玩仍是~

敲黑板,劃重點,initialValue值能夠被更新,除了下面兩種狀況:

1. 用戶手動更新表單數據,好比在<Input />組件中手動輸入,在<Select />組件中手動選擇等等,在用戶手動更新數據以後,initialValue的值改變不會更新表單值。
2. 當執行了setFieldsValue方法以後,initialValue的值改變不會更新表單值。

下面的例子中在生命週期函數componentDidMount中執行了setFieldsValue方法,其餘不變,你會發現無論怎麼點擊「從新獲取數據按鈕」,城市對應的值都不會被更新,而總量對應的值卻一直在更新。若是你手動改變總量的輸入,再點擊「從新獲取數據按鈕」,此時城市和總量的值都不會被更新。

import React, { Component } from 'react';
import { connect } from "dva";
import { InputNumber,Select,Form,Button } from "antd";

const FormItem = Form.Item;
const { Option } = Select;
const formItemLayout = {
labelCol: {

xs: { span: 24 },
sm: { span: 2 },

},
wrapperCol: {

xs: { span: 24 },
sm: { span: 22 },

},
};
@connect(({list})=>({
citys:list.citys,
detail:list.detail
}))
class CreateFrom extends Component {
componentDidMount(){

this.props.form.setFieldsValue({city:"上海"});

}
getDetail = () => {

this.props.dispatch({type:"list/fetchDetail"});

}
render() {

const { form,detail={},citys=[] } = this.props;
const { getFieldDecorator } = form;
const { city,count } = detail;
return (
  <Form>
    <Button onClick={this.getDetail}>從新獲取數據</Button>
    <FormItem
      {...formItemLayout}
      label="城市"
    >
      {getFieldDecorator('city', {
        initialValue: city,
        rules: [{ required: true, message: '請選擇城市' }],
      })(
        <Select style={{width:160}} placeholder="請選擇城市">
        {
          citys.map(item=><Option key={item} value={item}>{item}</Option>)
        }
        </Select>
      )}
    </FormItem>
    <FormItem
      {...formItemLayout}
      label="總量"
    >
      {getFieldDecorator('count', {
        initialValue:count,
        rules: [{ required: true, message: '總量(1-99999999)',pattern:/^[1-9][0-9]{0,7}$/ }],
      })(
        <InputNumber style={{width:160}}/>
      )}
    </FormItem>
  </Form>
);

}
}

export default Form.create()(CreateFrom);

貌似,表單的回顯出現一些起色。。。
3、碎碎念

不要一提表單回顯,就使勁往代碼裏面懟「setFieldsValue」,這樣會把代碼寫得很!很!很!很!很不優雅!!!

超級喜歡《鋒利的jQuery》封面上的這句話「每多學一點知識,就少寫一行代碼」,簡直是我寫代碼的信條。

數棧是雲原生—站式數據中臺PaaS,咱們在github和gitee上有一個有趣的開源項目:FlinkXFlinkX是一個基於Flink的批流統一的數據同步工具,既能夠採集靜態的數據,也能夠採集實時變化的數據,是全域、異構、批流一體的數據同步引擎。你們喜歡的話請給咱們點個star!star!star!

github開源項目:https://github.com/DTStack/fl...

gitee開源項目:https://gitee.com/dtstack_dev...

相關文章
相關標籤/搜索