我有两个React组件,分别是Form
和SimpleCheckbox
。
SimpleCheckbox
使用了一些Material UI组件,但我认为它们与我的问题无关。
在Form
中,useEffect调用api.getCategoryNames()
解析为一系列类别,例如['Information', 'Investigation', 'Transaction', 'Pain']
。
我的目标是访问父组件(Form
)中复选框的状态(是否选中)。我采用了this question中建议的方法。(请参阅已验证的答案)
有趣的是,当我登录checks
时,它给出了(在api调用解决之后):
{Pain: false}
我期望的是:
{
Information: false,
Investigation: false,
Transaction: false,
Pain: false,
}
此外,当我单击复选框时,checks
状态会正确更新。例如,假设我已选中Information
和Investigation
框,check
变为以下内容:
{
Pain: false,
Information: true,
Investigation: true,
}
以下是组件:
const Form = () => {
const [checks, setChecks] = useState({});
const [categories, setCategories] = useState([]);
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
}
useEffect(() => {
api
.getCategoryNames()
.then((_categories) => {
setCategories(_categories);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
{categories.map(category => {
<SimpleCheckbox
label={category}
onCheck={handleCheckChange}
key={category}
id={category}
/>
}
)
}
const SimpleCheckbox = ({ onCheck, label, id }) => {
const [check, setCheck] = useState(false);
const handleChange = (event) => {
setCheck(event.target.checked);
};
useEffect(() => {
onCheck(check, id);
}, [check]);
return (
<FormControl>
<FormControlLabel
control={
<Checkbox checked={check} onChange={handleChange} color="primary" />
}
label={label}
/>
</FormControl>
);
}
答案 0 :(得分:1)
您似乎在窗体级别和复选框组件级别两次控制状态。
我消除了其中一种状态并更改了处理程序。另外,我将检查设置为具有initialState,这样您就不会得到uncontrolled to controlled input warning
import React, { useState, useEffect } from "react";
import { FormControl, FormControlLabel, Checkbox } from "@material-ui/core";
import "./styles.css";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Form />
</div>
);
}
const Form = () => {
const [checks, setChecks] = useState({
Information: false,
Investigation: false,
Transaction: false,
Pain: false
});
const [categories, setCategories] = useState([]);
console.log("checks", checks);
console.log("categories", categories);
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
};
useEffect(() => {
// api
// .getCategoryNames()
// .then(_categories => {
// setCategories(_categories);
// })
// .catch(error => {
// console.log(error);
// });
setCategories(["Information", "Investigation", "Transaction", "Pain"]);
}, []);
return (
<>
{categories.map(category => (
<SimpleCheckbox
label={category}
onCheck={handleCheckChange}
key={category}
id={category}
check={checks[category]}
/>
))}
</>
);
};
const SimpleCheckbox = ({ onCheck, label, check }) => {
return (
<FormControl>
<FormControlLabel
control={
<Checkbox
checked={check}
onChange={() => onCheck(!check, label)}
color="primary"
/>
}
label={label}
/>
</FormControl>
);
};
如果您希望通过api动态提供服务来进行检查,则可以编写一个fetchHandler来等待api的结果并更新两个状态片
const fetchChecks = async () => {
let categoriesFromAPI = ["Information", "Investigation", "Transaction", "Pain"] // api result needs await
setCategories(categoriesFromAPI);
let initialChecks = categoriesFromAPI.reduce((acc, cur) => {
acc[cur] = false
return acc
}, {})
setChecks(initialChecks)
}
useEffect(() => {
fetchChecks()
}, []);
我对categoryFromFrom变量进行了硬编码,请确保在您的api调用语句之前添加await
。
let categoriesFromApi = await axios.get(url)
最后,将您的初始状态切片设置为空对象
const [checks, setChecks] = useState({});
答案 1 :(得分:0)
我所缺少的是在<Jenkins_URL>/job/<job_name>/config.xml
中使用功能更新。 Hooks API Reference说:setChecks
因此更改后:
If the new state is computed using the previous state, you can pass a function to setState.
到
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
}
它已开始按预期工作。