import React, { HTMLAttributes, ReactElement, useCallback, useContext } from 'react';
import styled from 'styled-components';
import { Validate } from '../Input/Input';
import { ctx } from './Form';
export interface FormItemProps extends HTMLAttributes {
label?: string;
rules?: Validate[];
children?: React.ReactNode;
}
// 不知道react的虚拟节点什么类型所以扩充vNode类型来消除ts警告
type VNode = ReactElement & { type: { name: string } };
const FormItemStyled = styled.div`
width: 100%;
display: flex;
justify-content: center;
align-items: center;
`;
const FormItem: React.FC = (props) => {
const { user, setUser, finishCallback, haveErr, setErr } = useContext(ctx);
const { children, label, rules, ...rest } = props;
const callback = useCallback(
(value: string, err: string[]) => {
const userObj: { [key: string]: string } = {};
userObj[label!] = value;
setUser((state) => ({ ...state, ...userObj }));
const errObj: { [key: string]: string[] } = {};
errObj[label!] = err;
setErr((state) => {
return { ...state, ...errObj };
});
},
[haveErr, user]
);
const buttonClick = useCallback(() => {
let err = false;
// eslint-disable-next-line guard-for-in,no-restricted-syntax
for (const key in haveErr) {
if (haveErr[key][0]) {
err = true;
}
}
if (err) {
finishCallback({ fail: haveErr });
} else {
finishCallback({ success: user });
}
}, [user, haveErr]);
const render = () => {
return React.Children.map(children, (child) => {
const vNode = child as VNode;
if (React.isValidElement(vNode) && vNode.type.name === 'Input') {
return React.cloneElement(vNode, { callback, rules });
}
if (React.isValidElement(vNode) && vNode.type.name === 'Button') {
return React.cloneElement(vNode, {
onClick: () => {
buttonClick();
}
});
}
return vNode;
});
};
return {render()};
};
FormItem.defaultProps = {
rules: [],
label: '请修改标签',
children: ''
};
export default React.memo(FormItem);