我有两个React组件,即Form
和SimpleCheckbox
SimpleCheckbox
使用了一些重要的UI组件,但我相信它们与我的问题无关。
在表单中
,使用effect调用api.getCategoryNames()
,该函数解析为一个类别数组,例如,[“信息”、“调查”、“交易”、“痛苦”]
。
我的目标是访问父组件(表单
)中复选框的状态(选中或未选中)。我采取了这个问题中建议的方法。(见验证答案)
有趣的是,当我记录检查
时,它给出了(api调用解析后):
{Pain: false}
我所期望的是:
{
Information: false,
Investigation: false,
Transaction: false,
Pain: false,
}
此外,当我单击复选框时,
会正确检查
状态更新。例如,假设我已经选中了Information
和调查
框,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>
);
}
我缺少的是在setChecks中使用功能更新。钩子API参考说:如果使用以前的状态计算新状态,您可以将函数传递给setState。
所以改变后:
const handleCheckChange = (isChecked, category) => {
setChecks({ ...checks, [category]: isChecked });
}
到
const handleCheckChange = (isChecked, category) => {
setChecks(prevChecks => { ...prevChecks, [category]: isChecked });
}
它已经开始像我预期的那样工作了。
看起来您需要两次控制状态,分别在表单级别和复选框组件级别。
我消除了其中一个状态并更改了处理程序。此外,我将检查设置为具有initialState,这样您就不会得到非受控到受控输入警告
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()
}, []);
我硬编码了categoriesFromApi变量,请确保在api调用语句前面添加wait
。
let categoriesFromApi = await axios.get(url)
最后,将状态的初始切片设置为空对象
const [checks, setChecks] = useState({});
问题内容: 在React中,这两种实现之间有什么真正的区别?一些朋友告诉我,FirstComponent是模式,但是我不明白为什么。SecondComponent看起来更简单,因为渲染仅被调用一次。 第一: 第二: 更新:我将setState()更改为this.state = {}(感谢joews),但是,我仍然看不到区别。一个比另一个好吗? 问题答案: 应该注意的是,复制永远不会更改为状态的属性
问题内容: 在React中,这两种实现之间有什么真正的区别?一些朋友告诉我,FirstComponent是模式,但是我不明白为什么。SecondComponent似乎更简单,因为渲染仅被调用一次。 第一: 第二: 更新:我将setState()更改为this.state = {}(感谢乔伊斯),但是,我仍然看不到区别。一个比另一个好吗? 问题答案: 应该注意的是,复制永远不会更改为状态的属性是一种
我有两个组件:父组件,我想改变子组件的状态: 和子组件: 我需要从父组件更改子组件的打开状态,或者当单击父组件中的按钮时,从父组件调用子组件的toggleMenu()?
假设我的父组件有两个子组件: 我从Child2获得一个输入,并将其传递给父组件(到目前为止,我知道该怎么做)。但是,我需要将该输入传递给Child1,以更新它的状态。 我怎么能那么做?
我想访问
我已经开始学习ReactJS,有一个关于无状态和有状态组件的问题。一般来说,我遵循组件和容器的分离,如下所示。有状态函数在组件文件夹中,其他逻辑操作在容器文件夹下。文件夹结构 让我们思考材料UI下拉列表。 为了打开和关闭下拉菜单和方法更改打开状态,这意味着它是有状态组件。但没有其他变化(省略年龄设置)。它似乎是可重用的组件,但包括状态与非常简单的操作,如打开和关闭。我应该放入哪个文件夹?容器还是组