如何让 setState 在函数式 React 组件的事件处理程序中工作



我正在重构一个 MERN 应用程序以使用钩子和上下文,所以我正在将类组件更改为函数。 一个组件具有根据输入字段中的击键更改状态的表单,例如:

class CreateAccountComp extends Component {
constructor(props) {
super(props);
this.state = {
firstName: null,
lastName: null,
email: null,
password: null,
githubID: null,
};
}
handleSubmit = (e) => {
e.preventDefault();
this.props.handleInputChange();
API.getsync(this.state.githubID, this.state.firstName, this.state.lastName, this.state.email);
...
})
};
handleChange = (e) => {
e.preventDefault();
const { name, value } = e.target;
...
this.setState({ [name]: value }, () => null);
};
....

这在回调添加到"this.setState"语句后有效。

新组件如下所示:

const CreateAccountComp = (props) => {
const [state, setState] = useState({
firstName: null,
lastName: null,
email: null,
password: null,
githubID: null,
});
const handleSubmit = (e) => {
e.preventDefault();
console.log("HMMMM leaving CreateAccountcomp");
props.handleInputChange();
API.getsync(state.githubID, state.firstName, state.lastName, state.email);
...
};
const handleChange = (e) => {
e.preventDefault();
const { name, value } = e.target;
...
setState({ [name]: value });
};

现在,我无法使用回调来处理异步setState语句,并且传递给API.getsync()函数的状态属性是未定义的。

我的研究提出了使用 async/await 或 useEffect 的例子,但它们都处理对外部 API 的单个调用。 在这里,我运行handleChange将击键呈现到表单中的输入字段中,然后通过onSubmit运行handleSubmit以执行一个函数以根据状态值更新数据库。 有没有办法在此函数组件中正确更新状态?

您可以使用useEffect钩子并将state作为依赖项添加到useEffect钩子中,以便每次state对象更改时它都会运行

useEffect(() => {
// code to run every time `state` object changes
API.getsync(state.githubID, state.firstName, state.lastName, state.email);
}, [state]);

您也没有正确更新状态。与将以前的状态与新状态合并this.setState不同,钩子返回useState函数将用新状态覆盖以前的状态。

为避免覆盖状态,请确保手动将以前的状态与新状态合并

const handleChange = (e) => {
e.preventDefault();
const { name, value } = e.target;
setState({ ...state, [name]: value });
};

请记住,useEffect钩子也将在组件首次渲染时运行。之后,它仅在更改state对象时运行。

编辑:

如果您不想在组件的初始呈现时useEffect运行时发出 HTTP 请求,请在useEffect钩子的回调中添加一个if语句,以确保仅在state对象中有发出 HTTP 请求所需的数据时才发出 HTTP 请求

useEffect(() => {
if (state.githubID) {
API.getsync(state.githubID, state.firstName, state.lastName, state.email);
}
}, [state]);

Yousaf让我走上了正确的轨道,但是,代码需要修改才能工作。 这个问题是,通过在初始加载时执行"API.getsync(state.githubID, state.firstName, state.lastName, state.email(;",数据库正在接收数据,这告诉应用程序来自github的用户信息在那里,并且输入用户名的表单永远不会呈现。 显然,如果用户名未定义,github api 将使用有效但不正确的信息进行响应。 通过以下方式点击 api:

axios
.get(
"https://api.github.com/users/" + developerLoginName + "/repos?type=all"

这导致用户"null"的 4 个存储库的信息被添加到数据库中!

此问题已通过从useEffect中删除调用getsync函数的行来解决。

但是,我发现根本不需要useEffect。 只需将传播运算符添加到"setState"即可使其工作。

相关内容

  • 没有找到相关文章

最新更新