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

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

1、initialValue的出處和定義

initialValue的出處:git

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

連接地址:https://ant.design/components/form-cn/#getFieldDecorator(id,-options)-%E5%8F%82%E6%95%B0antd

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

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

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

 

 

2、initialValue和defaultValue的區別

1. defaultValue的例子fetch

import React, { Component,Fragment } from 'react';
import { Button,Input } from "antd";
export default class CreateFrom extends Component {
  state={value:"value"}
  updateValue = () => {
    this.setState({value:"newValue"})
  }
  render() {
    return (
      <Fragment>
        <Button onClick={this.updateValue}>更新value</Button>
        <Input defaultValue={this.state.value} />
      </Fragment>
    );
  }
}

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

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

2. 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/flinkx

gitee開源項目:https://gitee.com/dtstack_dev_0/flinkx  

相關文章
相關標籤/搜索