我对反应和钩子很陌生,我正在努力解决useEffect()
。 我已经看了所有的视频并阅读了所有文档,但仍然无法完全理解我遇到的错误。(当我的新文章路由加载时,"onInput 不是一个函数"(。onInput 指向我的form-hook.js
中的回调函数。 为什么不注册?
在我的input.js
组件中:
import React, { useReducer, useEffect } from 'react';
import { validate } from '../../util/validators';
import './Input.css';
const inputReducer = (state, action) => {
switch (action.type) {
case 'CHANGE':
return {
...state,
value: action.val,
isValid: validate(action.val, action.validators)
};
case 'TOUCH': {
return {
...state,
isTouched: true
}
}
default:
return state;
}
};
const Input = props => {
const [inputState, dispatch] = useReducer(inputReducer, {
value: props.initialValue || '',
isTouched: false,
isValid: props.initialValid || false
});
const { id, onInput } = props;
const { value, isValid } = inputState;
useEffect(() => {
console.log(id);
onInput(id, value, isValid)
}, [id, value, isValid, onInput]);
const changeHandler = event => {
dispatch({
type: 'CHANGE',
val: event.target.value,
validators: props.validators
});
};
const touchHandler = () => {
dispatch({
type: 'TOUCH'
});
};
//if statement to handle if you are updating an article and touch the category.... but it's valid
const element =
props.element === 'input' ? (
<input
id={props.id}
type={props.type}
placeholder={props.placeholder}
onChange={changeHandler}
onBlur={touchHandler}
value={inputState.value}
/>
) : (
<textarea
id={props.id}
rows={props.rows || 3}
onChange={changeHandler}
onBlur={touchHandler}
value={inputState.value}
/>
);
return (
<div
className={`form-control ${!inputState.isValid && inputState.isTouched &&
'form-control--invalid'}`}
>
<label htmlFor={props.id}>{props.label}</label>
{element}
{!inputState.isValid && inputState.isTouched && <p>{props.errorText}</p>}
</div>
);
};
export default Input;
useEffect(() => {onInput
指向组件NewArticle.js
onInput 道具,用户可以在其中输入新文章。
import Input from '../../shared/components/FormElements/Input';
import { useForm } from '../../shared/hooks/form-hook';
const NewArticle = () => {
const [formState, inputHandler] = useForm({
title: {
value: '',
isValid: false
}
}, false );
return (
<Input
id="title"
element="input"
type="text"
label="Title"
onInput={inputHandler}
/> );
};
export default NewArticle;
。然后在我form-hook.js
输入处理程序是一个回调。因此,onInput 通过道具指向回调函数。 它正在工作,将onInput注册为一个函数,然后,突然间它抛出了一个错误。什么给?
import { useCallback, useReducer } from 'react';
const formReducer = (state, action) => {
switch (action.type) {
case 'INPUT_CHANGE':
let formIsValid = true;
for (const inputId in state.inputs) {
if (!state.inputs[inputId]) {
continue;
}
if (inputId === action.inputId) {
formIsValid = formIsValid && action.isValid;
} else {
formIsValid = formIsValid && state.inputs[inputId].isValid;
}
}
return {
...state,
inputs: {
...state.inputs,
[action.inputId]: { value: action.value, isValid: action.isValid }
},
isValid: formIsValid
};
case 'SET_DATA':
return {
inputs: action.inputs,
isValid: action.formIsValid
};
default:
return state;
}
};
export const useForm = (initialInputs, initialFormValidity) => {
const [formState, dispatch] = useReducer(formReducer, {
inputs: initialInputs,
isValid: initialFormValidity
});
const inputHandler = useCallback((id, value, isValid) => {
dispatch({
type: 'INPUT_CHANGE',
value: value,
isValid: isValid,
inputId: id
});
}, []);
const setFormData = useCallback((inputData, formValidity) => {
dispatch({
type: 'SET_DATA',
inputs: inputData,
formIsValid: formValidity
});
}, []);
return [formState, inputHandler, setFormData];
};
谢谢,你们。
我可以给你一些关于如何重组代码的建议。这将最终解决您的问题。
-
维护单一事实来源
- UI 的当前状态应存储在单个位置。
- 如果状态由多个组件共享,则最佳选择是使用上下文 API (redux( 传递的化简器,或者将容器组件的状态作为 props 传递给输入组件(当前策略(。
- 这意味着您应该删除
Input
组件的inputReducer
。 onInput
prop 应更新容器组件中的状态,然后将新inputValue
传递给Input
组件。- DOM
input
元素应该直接调用onInput
,而不是作为副作用。 - 删除
useEffect
呼叫。
-
关注点分离
-
操作应与挂钩分开定义。传统上,动作是一个返回传递给调度的对象的函数。
-
我相当确定这里的useCallback调用对性能的损害大于帮助。例如,
inputHandler
可以像这样重组:
-
const inputChange = (inputId, value, isValid) => ({
type: 'INPUT_CHANGE',
value,
isValid,
inputId
})
export const useForm = (initialInputs, initialFormValidity) => {
const [formState, dispatch] = useReducer(formReducer, {
inputs: initialInputs,
isValid: initialFormValidity,
})
const inputHandler = (id, value, isValid) => dispatch(
inputChange(id, value, isValid)
)
}
- 了解如何在浏览器中使用
debugger
或断点。如果在useEffect
调用中放置断点,则可以快速诊断问题。