我是 React hooks 的新手,并且一直在尝试它们。我正在尝试编写一个 usePostForm Hook ,在其中我可以复制后状态并将其与新的后字段合并,但由于某种原因,我不断出现无限循环。我错过了什么?
const usePostForm = field => {
const [post, setPost] = useState({
title: '',
points: '',
course: '',
question: ''
});
const setFormPost = () => {
setPost({ ...post, ...field });
};
return [post, setFormPost];
};
稍后在另一个函数中,我将其称为
const [post,setPost]=usePostForm()
setPost({title:'hello'})
最佳答案
如何调用 setPost
是关键。在上面的示例中,每次组件重新渲染时,它都会一遍又一遍地调用 setPost
。
最简单的方法是在表单
内设置值。如果您使用表单元素,则可以使用 event.target
更新 useCallback
函数中的值。例如,将 useCallback
函数与 prevState
回调结合使用:
const usePostForm = () => {
const [values, setValues] = React.useState({
title: '',
points: '',
course: '',
question: ''
});
const setFormPost = React.useCallback(
({ target: { name, value } }) =>
setValues(prevState => ({ ...prevState, [name]: value })),
[setValues]
);
return [values, setFormPost];
};
其中name
和value
来自event.target
:
<input type="text" name="title" value={values.title} onChange={setFormPost} />
我发现这是利用具有多个属性的单个对象状态的最简单方法。然后您可以在 handleSubmit
中添加 field
(如果不需要控制)或将 field
添加到您的初始 useState
调用(如果需要将其作为初始值应用于字段)。
例如,这通过 useState
函数中的扩展语法
初始化值(单击下面的运行代码片段
按钮):
const usePostForm = field => {
const [values, setValues] = React.useState({
title: '',
points: '',
course: '',
question: '',
...field
});
const setFormPost = React.useCallback(
({ target: { name, value } }) =>
setValues(prevState => ({ ...prevState, [name]: value })),
[setValues]
);
return [values, setFormPost];
};
const Form = () => {
const [values, setFormPost] = usePostForm({
title: "Initial Title Value",
points: 1
});
const handleSubmit = e => {
e.preventDefault();
alert(JSON.stringify(values, null, 4));
};
return(
<form className="form" onSubmit={handleSubmit}>
<div className="input-container">
<p className="label">Title:</p>
<input
className="input"
type="text"
name="title"
placeholder=""
value={values.title}
onChange={setFormPost}
/>
</div>
<div className="input-container">
<p className="label">Points:</p>
<input
className="input"
type="number"
name="points"
placeholder=""
value={values.points}
onChange={setFormPost}
/>
</div>
<div className="input-container">
<p className="label">Course:</p>
<input
className="input"
type="text"
name="course"
placeholder=""
value={values.course}
onChange={setFormPost}
/>
</div>
<div className="input-container">
<p className="label">Question:</p>
<input
className="input"
type="text"
name="question"
placeholder=""
value={values.question}
onChange={setFormPost}
/>
</div>
<div className="btn-container">
<button className="btn primary" type="submit">Submit</button>
</div>
</form>
);
}
ReactDOM.render(
<Form />,
document.getElementById('root')
);
html {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
font-size: 16px;
font-weight: 400;
line-height: 1.5;
-webkit-text-size-adjust: 100%;
background: #fff;
color: #666;
}
.btn {
color: #fff;
border: 1px solid transparent;
margin: 0 10px;
cursor: pointer;
text-align: center;
box-sizing: border-box;
padding: 0 30px;
vertical-align: middle;
font-size: .875rem;
line-height: 38px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: .1s ease-in-out;
transition-property: color,background-color,border-color;
}
.btn:focus {
outline: 0;
}
.btn-container {
text-align: center;
margin-top: 10px;
}
.form {
width: 550px;
margin: 0 auto;
}
.danger {
background-color: #f0506e;
color: #fff;
border: 1px solid transparent;
}
.danger:hover {
background-color: #ee395b;
color: #fff;
}
.error {
margin: 0;
margin-top: -20px;
padding-left: 26%;
color: red;
text-align: left;
}
.input {
display: inline-block;
height: 40px;
font-size: 16px;
width: 70%;
padding: 0 10px;
background: #fff;
color: #666;
border: 1px solid #e5e5e5;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
transition: .2s ease-in-out;
transition-property: color,background-color,border;
}
.input:focus {
outline: 0;
border: 1px solid #1e87f0;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
.input-container {
width: 100%;
height: 60px;
margin-bottom: 20px;
display: inline-block;
}
.label {
width: 25%;
padding-top: 8px;
display: inline-block;
text-align: center;
text-transform: uppercase;
font-weight: bold;
height: 34px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
background: rgb(238, 238, 238);
}
.primary {
background-color: #1e87f0;
}
.primary:hover {
background-color: #0f7ae5;
color: #fff;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id='root'>
</div>
关于javascript - 使用 react 钩子(Hook)时的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57946107/