目录
一、antd getFieldDecorator使用rules不起作用
3.在componentWillUnmount()中移除监听器
四、一个页面调用的多个相同组件,导致props相互影响的问题
一、antd getFieldDecorator使用rules不起作用
(一)问题描述
使用getFieldDecorator的rules规则限制,只提示而不终止函数给出相应的提示。
例如,在一个modal弹窗中,一个输入框不符合rules规则时候会提出相应的提示,但是,点击‘保存’或者‘确定’的时候仍然能执行后台api且关闭。
(二)解决问题
原因:缺少validateFields()验证。
解决如下:
无法完场终止函数验证是因为缺少下面这段代码,加上即可。
this.props.form.validateFields((err, vals) => {
if (!err) {
}
})
二、监听页面宽度动态
1.在componentDidMount()中加入监听器
componentDidMount() {
this.screenChange();
}
screenChange() {
window.addEventListener('resize', this.resize);
}
resize()方法中,定义了屏幕尺寸变化后需要执行的代码,可定义一个state,在resize中赋值
2.在constructor中绑定resize()
constructor(props) {
this.resize.bind(this);
}
3.在componentWillUnmount()中移除监听器
componentWillUnmount() {
window.removeEventListener('resize',this.resize);
}
注:一定要移除监听器,否则多个组件之间会导致this的指向紊乱!!!
三、联动下拉框清空问题
(上级改变,下级清空,select写在表单里,用了getFieldDecorator)
解决这个问题,不能用state传值,select是写在表单里的,用了getFieldDecorator所以浏览器就华丽的报错了,报错内容:
Warning: `getFieldDecorator` will override `value`, so please don't set `value` directly and use `setFieldsValue` to set it.
也不能使用initialValue,但是initialValue是设置初始值,只render执行一次就不执行了,需要使用setFieldsValue方法。注意:antd中form表单的setFieldsValue只能设置其他域的值,不能控制自己表单域的值。
想要setFieldsValue设置自己值使输入框受控,想把redux中传过来的props绑定到form,使props改变表单值实时改变,使用options.normalize。
官方解释:转换默认的 value 给控件;function(value, prevValue, allValues): any
const { getFieldProps } = this.props.form;
return (
<div>
<Select
{...getFieldProps('name', {
normalize: (value, prevValue, allValues) => {
let targetValues = []
const nowValues = prevValue || [];
if (nowValues.length > value.length) {
targetValues = value;
} else {
const selectValue = value.find(nv => nowValues.indexOf(nv) === -1)
if (selectValue === '0') {
targetValues = ['0']
} else {
targetValues = value.filter(x => x !== '0');
}
}
return targetValues;
}
})}
style={{ width: 800 }}
mode="multiple"
>
{data.map((item) => <Option key={item.value}>{item.name}</Option>)}
</Select>
</div>
);
以上是 normalize 的代码,通过转换返回新的值,不会出现两次渲染。
要实现联级下拉框清空,使用如下:
//效果:第一行改变,会置空其后组件的值 和 第二行组件的值
{getFieldDecorator(fieldName, {
rules: fieldConfig.rules || [{ required: false, message: '' }],
initialValue: initialValue[fieldName],
normalize:(value, prevValue) => {
//index是行序数(从0开始),length是一行内的组件数,
//i是此行内的组件序数(从0开始),count为此时的组件坐标位置
//如果不限制为第一行的话,const count = i + length * index;不再适用
const count = i + length * index;
if (value !== prevValue && index < 1) {
//触发变值时记录位置,赋给全局变量countValue,只记录第一行
countValue = count;
} else if (countValue < count && index < 2) {
//触发变值的组件在该组件的位置前,置空其后组件的值,不置空第三行
return '';
}
return value;
}
}
但在一些复杂特殊的情况下,依然不能实现相关需求,建议使用相关变量作为React组件的key值,强制两次渲染。
四、一个页面调用的多个相同组件,导致props相互影响的问题
不能要复用的组件获取数据也连到redux里面的,不可能通过dispatch来发出消息,会相互影响的。
解决方法一:直接在组件内部发请求,而不是通过redux或者dvajs,里面的数据都是直接在组件里面直接fetch的,然后用state保存。
举例如下:
export async function getCount(params) {
return request(url, params);
}
export default class ShowCount extends React.Component {
constructor() {
super();
this.state = {
loading: true,
count: 0,
};
}
@Bind
loadCount() {
const { params } = this.props;
let count = 0;
try {
count = await getTunnelCountByRegion(region);
sessionStorage.setItem(region, count);
} catch (err) {
message.error(`fail to query count`);
}
this.setState({
loading: false,
count,
});
}
componentDidMount() {
this.loadCount();
}
render() {
return this.state.loading ?
<Icon style={{ paddingLeft: 12 }} type="loading" />
: (this.state.count);
}
}
五、可伸缩列的表格
需要我们把react-resizable中的styles.css引入或者复制到当前app.css中才能使用
import '../node_modules/react-resizable/css/styles.cs