React Hooks MUI ,父子传值,双向绑定,memo,useCallback 用法。
- useCallback 配合 memo使用避免重复渲染子组件。
- 子组件封装成表单,方便直接调用。
子组件
import { useState, memo } from "react";
import {
Grid,
FormControl,
FormLabel,
FormControlLabel,
Checkbox,
FormGroup,
TextField,
InputLabel,
Select,
MenuItem,
RadioGroup,
Radio,
} from "@mui/material";
const ComponentsForm = memo((props: any) => {
console.log("子组件更新...");
// props
const { setFormData, parentFormData, isDisable } = props;
// 通用逻辑
const handleChange = (event: any) => {
const { name, value, type, checked } = event.target;
const newValue = type === "checkbox" ? checked : value;
setFormData((prevValues: any) => ({
...prevValues,
[name]: newValue,
}));
};
const [CheckboxList, setCheckboxList] = useState([
{ id: "0",name: "苹果",value: "1", isCheck: false, },
{ id: "1", name: "香蕉",value: "2",isCheck: false,},
{ id: "2", name: "橘子", value: "3", isCheck: false },
]);
// 获取勾选处理
const list = parentFormData.experimentProject.split(",");
for (const item of CheckboxList) {
for (const v of list) {
if (item.value === v) {
item.isCheck = true;
}
}
}
// 单个复选框逻辑;
const handleCheckChange = (event: any) => {
let newCheckboxList = [...CheckboxList];
newCheckboxList[event.target.id].isCheck = event.target.checked;
setCheckboxList(newCheckboxList);
// 判断是否选中且返回数组对象
// eslint-disable-next-line array-callback-return, consistent-return
const newCheckboxListStr = newCheckboxList.map((v: any) => {
return v.isCheck === true ? v.value : undefined;
});
console.log(newCheckboxListStr);
// 删除undefined
const CheckStr = newCheckboxListStr.filter((res: string) => {
return res !== undefined;
});
setFormData((preVal: any) => {
return {
...preVal,
experimentProject: CheckStr.join(),
};
});
};
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<FormControl>
<FormLabel id="demo-row-radio-buttons-group-label">
实验项目
</FormLabel>
<FormGroup row>
{CheckboxList.map((v) => (
<FormControlLabel
key={v.id}
control={
<Checkbox
disabled={isDisable}
checked={v.isCheck}
onChange={handleCheckChange}
name={v.name}
size="small"
id={v.id}
/>
}
label={v.value}
/>
))}
</FormGroup>
</FormControl>
</Grid>
<Grid item xs={4}>
<FormControl>
<FormLabel id="demo-row-radio-buttons-group-label">性别</FormLabel>
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="radioValue"
value={parentFormData.radioValue}
onChange={handleChange}
>
<FormControlLabel value="女" control={<Radio />} label="女" />
<FormControlLabel value="男" control={<Radio />} label="男" />
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={4}>
<TextField
disabled={isDisable}
fullWidth
required
id="outlined-required"
label="数量"
name="experimentWorkQuantity"
value={parentFormData.experimentWorkQuantity}
onChange={handleChange}
/>
</Grid>
<Grid item xs={4}>
<TextField
disabled={isDisable}
fullWidth
id="outlined-basic"
label="开始时间"
variant="outlined"
name="planStartDate"
value={parentFormData["planStartDate"]}
onChange={handleChange}
/>
</Grid>
<Grid item xs={4}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">需求是否合理</InputLabel>
<Select
name="needReasonableIdForNonDestroy"
disabled={isDisable}
labelId="demo-simple-select-label"
id="demo-simple-select"
value={parentFormData.needReasonableIdForNonDestroy}
label="是否合理"
onChange={handleChange}
>
<MenuItem value="1">是</MenuItem>
<MenuItem value="0">否</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={4}>
{/* 直接设置对象值,不用handleChange */}
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">是否已确认</InputLabel>
<Select
disabled={isDisable}
labelId="demo-simple-select-label"
id="demo-simple-select"
name="planConfirmId"
value={parentFormData.planConfirmId}
label="是否已确认"
onChange={(event) => {
setFormData((prevValues: any) => {
return {
...prevValues,
planConfirmId: event.target.value,
};
});
}}
>
<MenuItem value="1">是</MenuItem>
<MenuItem value="0">否</MenuItem>
</Select>
</FormControl>
</Grid>
</Grid>
);
});
export default ComponentsForm;
父组件
import { useEffect, useState, useCallback } from "react";
import ComponentsForm from "./SubForm";
import { Paper, TextField, Button, Grid } from "@mui/material";
const Customer = () => {
const [scheduleDisable, setScheduleDisable] = useState(false);
const [scheduleForm, setScheduleForm] = useState({
needReasonableIdForNonDestroy: "",
experimentProject: "",
experimentWorkQuantity: "",
planStartDate: "",
planEndDate: "",
autoGeneratePlan: "",
autoGeneratePlanId: "",
planConfirmId: "",
planConfirm: "",
checkboxValue: false,
radioValue: "",
option2: "",
});
const handleChildValuesChange = useCallback((val: any) => {
setScheduleForm(val);
}, []);
const [num, setNum] = useState(1);
useEffect(() => {
console.log(scheduleForm);
}, [scheduleForm]);
useEffect(() => {
console.log(num);
}, [num]);
return (
<Paper>
<div>
{/* 验证 useCallback 是否有效*/}
<Button
variant="outlined"
onClick={() => {
setNum((val) => val + 1);
}}
>
点击加工资
</Button>
</div>
<ComponentsForm
setFormData={handleChildValuesChange}
parentFormData={scheduleForm}
isDisable={scheduleDisable}
/>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
fullWidth
id="outlined-required"
label="备注"
value={scheduleForm.autoGeneratePlan}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setScheduleForm({
...scheduleForm,
autoGeneratePlan: event.target.value,
});
}}
/>
</Grid>
</Grid>
</Paper>
);
};
export default Customer;