记录react
一、框架使用
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合并操作后的最终值;