UseEffect 和 useCallback 仍然导致反应项目中的无限循环
UseEffect and useCallback still causes infinite loop in react project
我似乎无法解决我的 React 项目中的无限循环问题。
我正在开发一个每日日志 React 应用程序。让我简要解释一下这个项目。下面是快速查看代码的图片:
底部有相同的代码。
结构(从上到下)
DailyLog
组件有一个使用 Question
组件的表单,道具被传递到其中。
Question
组件使用道具来显示问题和描述。它还包含一个 Input
组件,props 将进一步传递到该组件中。
Input
组件接受道具并呈现适当的表单输入字段。
逻辑(从下到上)
Input
组件处理它自己的 inputState
。当用户输入内容并触发 onChangeHandler
时,状态会发生变化。
Input
组件还有一个 useEffect()
挂钩,它调用一个 onInput()
函数,该函数作为 props 从 DailyLog
. 传递下来
DailyLog
组件中的 onInputHandler()
更新 formState
,这是包含所有输入字段值的表单范围状态。 formState
根据当时填写的输入字段进行修改。
onInputHandler()
使用 useCallback()
钩子,它应该停止由任何 parent/child 重新渲染引起的无限循环。但它不起作用 :frowning:
代码有什么问题?我在这里错过了什么?代码如下:
//DailyLog.js
import React, { useState, useCallback } from 'react';
import Question from '../components/FormElements/Question';
import questionData from '../components/DailyLog/questionData';
import './DailyLog.css';
const DailyLog = () => {
const [formState, setFormState] = useState();
const onInputHandler = useCallback(
(inputId, inputValue) => {
setFormState({
...formState,
[inputId]: inputValue,
});
},
[formState]
);
return (
<main className="container">
<form action="" className="form">
<Question
id="title"
element="input"
type="text"
placeholder="Day, date, calendar scheme"
onInput={onInputHandler}
/>
<Question
id="focus"
question={questionData.focusQuestion}
description={questionData.focusDescription}
element="textarea"
placeholder="This month's focus is... This week's focus is..."
onInput={onInputHandler}
/>
</form>
</main>
);
};
export default DailyLog;
//Question.js
import React from 'react';
import Input from './Input';
import './Question.css';
const Question = props => {
return (
<div className="form__group">
{props.question && (
<label className="form__label">
<h2>{props.question}</h2>
</label>
)}
<small className="form__description">{props.description}</small>
<Input
id={props.id}
element={props.element}
type={props.type}
placeholder={props.placeholder}
onInput={props.onInput}
/>
</div>
);
};
export default Question;
//Input.js
import React, { useState, useEffect } from 'react';
import './Input.css';
const Input = props => {
const [inputState, setInputState] = useState();
const { id, onInput } = props;
useEffect(() => {
onInput(id, inputState);
}, [id, onInput, inputState]);
const onChangeHandler = event => {
setInputState(event.target.value);
};
// check if question element type is for input or textarea
const element =
props.element === 'input' ? (
<input
id={props.id}
className="form__field"
type={props.type}
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
) : (
<textarea
id={props.id}
className="form__field"
rows="1"
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
);
return <>{element}</>;
};
export default Input;
从 useEffect 敏感度列表中删除 id 和 onInput
useEffect(() => {
onInput(id, inputState);
}, [inputState]);
并将 inputState 的默认值设置为 '',如下所示:
const [inputState, setInputState] = useState('');
防止'A component is changing an uncontrolled input of type text to be controlled error in ReactJS'。你也可以初始化 formState:
const [formState, setFormState] = useState({title:'', focus:''});
我似乎无法解决我的 React 项目中的无限循环问题。
我正在开发一个每日日志 React 应用程序。让我简要解释一下这个项目。下面是快速查看代码的图片:
底部有相同的代码。
结构(从上到下)
DailyLog
组件有一个使用Question
组件的表单,道具被传递到其中。Question
组件使用道具来显示问题和描述。它还包含一个Input
组件,props 将进一步传递到该组件中。Input
组件接受道具并呈现适当的表单输入字段。
逻辑(从下到上)
Input
组件处理它自己的inputState
。当用户输入内容并触发onChangeHandler
时,状态会发生变化。Input
组件还有一个useEffect()
挂钩,它调用一个onInput()
函数,该函数作为 props 从DailyLog
. 传递下来
DailyLog
组件中的onInputHandler()
更新formState
,这是包含所有输入字段值的表单范围状态。formState
根据当时填写的输入字段进行修改。onInputHandler()
使用useCallback()
钩子,它应该停止由任何 parent/child 重新渲染引起的无限循环。但它不起作用 :frowning:
代码有什么问题?我在这里错过了什么?代码如下:
//DailyLog.js
import React, { useState, useCallback } from 'react';
import Question from '../components/FormElements/Question';
import questionData from '../components/DailyLog/questionData';
import './DailyLog.css';
const DailyLog = () => {
const [formState, setFormState] = useState();
const onInputHandler = useCallback(
(inputId, inputValue) => {
setFormState({
...formState,
[inputId]: inputValue,
});
},
[formState]
);
return (
<main className="container">
<form action="" className="form">
<Question
id="title"
element="input"
type="text"
placeholder="Day, date, calendar scheme"
onInput={onInputHandler}
/>
<Question
id="focus"
question={questionData.focusQuestion}
description={questionData.focusDescription}
element="textarea"
placeholder="This month's focus is... This week's focus is..."
onInput={onInputHandler}
/>
</form>
</main>
);
};
export default DailyLog;
//Question.js
import React from 'react';
import Input from './Input';
import './Question.css';
const Question = props => {
return (
<div className="form__group">
{props.question && (
<label className="form__label">
<h2>{props.question}</h2>
</label>
)}
<small className="form__description">{props.description}</small>
<Input
id={props.id}
element={props.element}
type={props.type}
placeholder={props.placeholder}
onInput={props.onInput}
/>
</div>
);
};
export default Question;
//Input.js
import React, { useState, useEffect } from 'react';
import './Input.css';
const Input = props => {
const [inputState, setInputState] = useState();
const { id, onInput } = props;
useEffect(() => {
onInput(id, inputState);
}, [id, onInput, inputState]);
const onChangeHandler = event => {
setInputState(event.target.value);
};
// check if question element type is for input or textarea
const element =
props.element === 'input' ? (
<input
id={props.id}
className="form__field"
type={props.type}
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
) : (
<textarea
id={props.id}
className="form__field"
rows="1"
value={inputState}
placeholder={props.placeholder}
onChange={onChangeHandler}
/>
);
return <>{element}</>;
};
export default Input;
从 useEffect 敏感度列表中删除 id 和 onInput
useEffect(() => {
onInput(id, inputState);
}, [inputState]);
并将 inputState 的默认值设置为 '',如下所示:
const [inputState, setInputState] = useState('');
防止'A component is changing an uncontrolled input of type text to be controlled error in ReactJS'。你也可以初始化 formState:
const [formState, setFormState] = useState({title:'', focus:''});