记录react

2021-11-18  本文已影响0人  不行了快拦住我

一、框架使用

antd pro component - EditableProTable 表单重置

受控情况之下,改变 dataSource之后,但是表格编辑组件还是记录上次编辑状态记录的数据,没有及时更新,解决办法就是手动更新表单(其实整个表格就是一个form)

  // 声明form实例
  const [form] = Form.useForm();
  console.log('打印formValues:',form.getFieldsValue());

 <EditableProTable<OrderCargoDtoType>
            // scroll={{ x: 1300 }}
            rowKey="id"
            columns={columnsArr(short_width, options, onSelect, onSearch)}
            // request={requestTableData}
            dataSource={dataSource}
            pagination={pageConfig}
            actionRef={tableRef}
            //onChange={setDataSource}
            rowSelection={{ ...rowSelection, checkStrictly: false }}
            toolBarRender={() => {
              return renderTableToolBar(save, handleExport, dataCensus, batch,openEdit);
            }}
            editable={{
              form:form,
              type: 'multiple',
              .....



//这里是修改dataSource的地方,也是需要更新表单的地方


 getData={(data: any) => {
              modifyRowKeys.forEach((ele, index) => {
                let i = dataSource.findIndex((item) => {
                  return item.id == ele;
                });

                for (let key in data) {
                   dataSource[i][key] = data[key];
                 }
              });
               setDataSource(dataSource);
               //------------------就是这里!!!--------------
              form.resetFields();
             }}

二、dva使用

新建js文件 为dva仓库
设置名称 namespace: 'company',
设置state: {
    enumeration: '', // 获取所有枚举
    options: optinons,
    default: 0,
    isExist: false,
    user: '', //用户信息
  },
effects内部为异步函数 不可修改state 需要put提交到reducers修改
*为省略写法的箭头函数
函数接收两个参数 {state},{ put, call}
state为仓库数据,put为提交到同步方法,内部为type函数名称,payload为提交参数
reducers内部为同步方法,唯一修改state数据方法,需要disptch提交,两个参数,type:’company/changeCompany‘,type写法为仓库名/函数名,payload为提交参数

const CompanySelet = {
  namespace: 'company',
  state: {
    enumeration: '', // 获取所有枚举
    options: optinons,
    default: 0,
    isExist: false,
    user: '', //用户信息
  },
  effects:{
    *getUser({state},{ put, call}){
      const { data = {}}=  yield call(getEmployeeWithCurrentUser);
      yield put({
        type:'setUser',payload:data
      });
    },
    *getEnu({state},{ put, call}){
      const { data = {}}=  yield call(getEnums, params.join(','));
      const res = {...data, ...list}
      let obj = {}
      let arr = []
      for (const item of paramsMap) {
        if(res[item]) {
          arr = Object.keys(res[item]).map(key => {
            return { code: res[item][key], desc: key }
          })
          obj[item] = arr
        }
      }
      yield put({
        type:'setEnu',payload:obj
      });
    }
  },
  reducers: {
    changeCompany(state, action) {
      //固定写法 return 返回整体state
      return {
        ...state,
        isExist: action.payload || false,
      };
    },
  },
};

export default CompanySelet;


组件内使用
import { connect } from 'dva';
const 组件名 = (props) => {
this.props.dispatch({
        type: 'company/getEnu',
        payload:{a:1}
      })
}
export default connect(({ company }) => ({  company}))(组件名);

// 重点: 首次进入网站,无法触发effect方法,需要在effect中使用try{}catch{}方法

三、antd pro proLayOut 菜单分割时

image.png

定义三级路由,使一级路由自动匹配到三级路由,必须在三级路由最后面加上一级路由的path和重定向,如果设置component,为显示当前一级路由页面

四、antd pro proLayOut 菜单分割时

[React中setState如何同步更新 ]

同步更新策略

1.完成回调

setState函数的第二个参数允许传入回调函数,在状态更新完毕后进行调用,譬如:

[ 复制代码

](javascript:void(0); "复制代码")

this.setState({
      load: !this.state.load,
      count: this.state.count + 1 }, () => {
      console.log(this.state.count);
      console.log('加载完成')
    });
[ 复制代码

](javascript:void(0); "复制代码")

2.Promise封装结合async/await

其实这里就是JavaScript异步编程相关知识,将上面回调写法换成Promise

引入Promise来封装setState:

setStateAsync(state) { return new Promise((resolve) => { this.setState(state, resolve)
    });
  }


setStateAsync 返回的是Promise对象,在调用时我们可以使用Async/Await语法来优化代码风格:

[![复制代码](https://img.haomeiwen.com/i2772613/5911975d5e684256.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

 async componentDidMount() {

       await this.setStateAsync ({

               count: this.state.count * 1 + 2

           })

           console.log(123, this.state.count)

           await this.setStateAsync ({

               count: this.state.count * 1 + 2

           })

           console.log(456, this.state.count)

[![复制代码](https://img.haomeiwen.com/i2772613/78af9cf7ed38c157.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

3.直接使用操作异步函数async / await

此时每次await setState都会执行一遍render方法

[![复制代码](https://img.haomeiwen.com/i2772613/66324513e63c57a4.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

handleChange = async () => {

           await this.setState({

               count: this.state.count * 1 + 2

           })

           console.log(123, this.state.count)

           await this.setState({

               count: this.state.count * 1 + 2

           })

           console.log(456, this.state.count)

}

[![复制代码](https://img.haomeiwen.com/i2772613/2c650c96164ae596.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

四、setState参数详解

state中定义count初始值为1;

1.第一个参数为传入对象;

[![复制代码](https://img.haomeiwen.com/i2772613/d75d1b488a117435.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

handleChange = () => { this.setState({
            count: this.state.count  + 2 })
        console.log(123, this.state.count) this.setState({
            count: this.state.count  + 2 })
        console.log(456, this.state.count)
    }

[![复制代码](https://img.haomeiwen.com/i2772613/1d4e7d1275a984ae.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

调用方法两次输出值为都为3;

React 出于性能方面的考虑,并不会直接对每次的调用都进行更新,而是会将多次传入的对象进行合并处理,以产生一个新的最终的 state 对象;

第二个参数为完成回调

[![复制代码](https://img.haomeiwen.com/i2772613/a1150a09da60229a.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

handleChange = () => { this.setState({
            count: this.state.count  + 2 }, () => {
            console.log(123, this.state.count)
        }) this.setState({
            count: this.state.count  + 2 }, () => {
            console.log(456, this.state.count)
        })
    }


[![复制代码](https://img.haomeiwen.com/i2772613/948777de8dd3fae9.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

与上面输出保持一致

2.第一个参数为传入函数:

[![复制代码](https://img.haomeiwen.com/i2772613/132169dc10cd60d4.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 
handleChange = () => { this.setState((prevState, props) => ({
            count: prevState.count + 2 }), () => {
            console.log(123, this.state.count)
        }) this.setState((prevState, props) => ({
            count: prevState.count + 2 }), () => {
            console.log(456, this.state.count)
        })
    }

[![复制代码](https://img.haomeiwen.com/i2772613/f087fcf2b5600d80.gif?imageMogr2/auto-orient/strip)](javascript:void(0); "复制代码") 

函数第一个参数接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数;

此时输出为两次都是5;

在第二次调用 setState 方法时便可以通过 prevState.count 拿到最新的值从而更新本次的 state 。显然,React 对于传入函数的方式和传入对象的方式进行更新 state 的各自具体理念是不一样的,对于传入函数的方式,在调用 setState 进行更新 state 时,React 会按照各个 setState 的调用顺序,将它们依次放入一个队列,然后,在进行状态更新时,则按照队列中的先后顺序依次调用,并将上一个调用结束时产生的 state 传入到下一个调用的函数中,当然,第一个 setState 调用时,传入的 prevState 则是当前的 state ,如此,便解决了传入对象式调用 setState 方法所存在的 不能依赖上一次的 state 去计算本次 state 的问题。

[ 复制代码

](javascript:void(0); "复制代码")

<pre style="margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: background-color, border-color, border-radius, padding, margin, color, opacity; overflow: auto; font-family: "Courier New"; font-size: 12px; overflow-wrap: break-word;">handleChange = () => { this.setState((prevState, props) => ({
count: prevState.count + 2 }), () => {
console.log(123, this.state.count)
}) this.setState((prevState, props) => ({
count: this.state.count + 2 }), () => {
console.log(456, this.state.count)
})
}</pre>

[ 复制代码

](javascript:void(0); "复制代码")

值得一提的是,在上面的这段代码中,执行第二个 setState 里面的函数时,由第一个 setState 所产生的最新的 state 并没有合并到 this 对象上面去,所以此时通过 this.state 获取不到最新的状态,故而在函数内部拿到的 this.state.count 的值为 1 而非 3。

另外,不论第一个参数是何种类型,多次setState也只会调用一次render方法,第二个参数callback完成回调中获取this.state的值同样也是多次setState合并操作后的最终值;

上一篇下一篇

猜你喜欢

热点阅读