javascript - 具有提升状态和受控依赖的 React 表单提交逻辑

标签 javascript reactjs react-hooks

为了尝试使用 React hooks,我用这个组件给自己挖了一个很深的兔子洞。

父组件处理最终分发到多个组件的字典状态。

我的问题子组件 WordInput 有一个带有单个输入的表单。提交表单时,组件从 API 获取单词的定义,并将单词和定义传递给父级,然后父级以字典的形式设置状态。到目前为止,如果它是字典中的第一个单词,那就太好了。我遇到麻烦的部分是提交任何后续单词/定义。

当用户提交后续单词时,我希望组件检查该单词是否已存在于传递给子项的字典中。如果不存在,请通过提交功能将其添加到字典中。

我认为问题是我试图用 useEffect 做太多事情 我 useEffect 来: - 设置加载 - 检查并处理字典中现有的单词 - 检查定义和单词是否不为空并将两者提交给父/词典 - 从 API 获取定义

在未处理的代码中,我有多个 console.groups 来帮助我跟踪正在发生的情况。添加到组件中的越多,子组和子组的子组就越多。显然,我采用的方法不是很干燥,并且会导致组件/useEffect 函数的过多重新渲染。为了简洁起见,我删除了 console.log 条目。

导入的fetchWordDefinition仅处理获取的数据并将其正确排列到数组中。

我不知道如何保持干燥和有效,对于这个相当简单的任务,我们将不胜感激。我的直觉是保留提交处理程序中提交单词/定义的所有逻辑,并且仅使用 useEffect 来验证之前的数据。

import React, { useState, useEffect } from "react";
import fetchWordDefinition from "./lib/utils";

const WordInput = ({ onSubmit, dictionary }) => {
    const [definition, setDefinition] = useState([]);
    const [cause, setCause] = useState({ function: "" });
    const [error, setError] = useState({});
    const [loading, setLoading] = useState(false);
    const [word, setWord] = useState("");
    const [wordExistsInDB, setWordExistsInDB] = useState(false);

    useEffect(() => {
        const dictionaryEmpty = dictionary.length === 0 ? true : false;

        if (dictionaryEmpty) {
            return;
        } else {
            for (let i = 0; i < dictionary.length; i += 1) {
                if (dictionary[i].word === word) {
                    setWordExistsInDB(true);
                    setError({ bool: true, msg: "Word already exists in DB" });
                    break;
                } else {
                    setWordExistsInDB(false);
                    setError({ bool: false, msg: "" });
                }
            }
        }
    }, [dictionary, word]);

    useEffect(() => {
        const definitionNotEmpty = definition.length !== 0 ? true : false;
        const wordNotEmpty = word !== "" ? true : false;

        if (wordNotEmpty && definitionNotEmpty && !wordExistsInDB) {
            onSubmit(word, definition);
            setWord("");
            setDefinition([]);
        }
    }, [definition, word, onSubmit, wordExistsInDB]);

    useEffect(() => {
        if (cause.function === "fetch") {
            async function fetchFunction() {
                const fetch = await fetchWordDefinition(word);
                return fetch;
            }

            fetchFunction().then(definitionArray => {
                setDefinition(definitionArray);
                setCause({ function: "" });
            });
        }
    }, [cause, word]);

    const handleSubmit = async e => {
        e.preventDefault();

        setLoading(true);
        setCause({ function: "fetch" });
    };

    return (
        <form onSubmit={handleSubmit}>
            {error.bool ? <span>{error.msg}</span> : null}
            <input
                name='word'
                placeholder='Enter Word'
                type='text'
                value={word}
                onChange={({ target: { value } }) => setWord(value)}
            />
            <input type='submit' />
        </form>
    );
};

export default WordInput;

最佳答案

确实发生了不必要的 useEffect 事件以及大部分状态。您所需要的只是 handleSubmit 来进行提取。

const WordInput = ({ onSubmit, dictionary }) => {
  const [word, setWord] = React.useState("");
  const handleChange = React.useCallback(e => {
    setWord(e.currentTarget.value)
  }, [])
  const handleSubmit = React.useCallback(() => {
    //check if word is in dictionary
    const wordIsAlreadyThere = dictionary.map(entry => entry.word).includes(word)
    //fetch the definition, wait for it, and call submit
    if(!wordIsAlreadyThere && word.length > 0){
      fetchWordDefinition(word)
        .then(definition => {
          onSubmit(word, definition)
          setWord('')
        }).catch(err => console.log(err))
    }
  }, [])
  return (
    <form onSubmit={handleSubmit}>
      <input
        value={word}
        onChange={handleChange}/>
      <input type='submit' />
     </form>
  );
}

关于javascript - 具有提升状态和受控依赖的 React 表单提交逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60311586/

相关文章:

javascript - 高阶组件 (HOC) 和窗口调整大小监听器

javascript - 使用重新图表 React hooks AreaChart 控制台警告

javascript - React 自定义 Hook 不触发 DOM 更新

javascript - useContext 未在回调中更新其值

javascript - JQuery 按钮在引用表单字段中的值启用后单击时禁用

javascript - 在另一个构造函数中调用构造函数

javascript - React Enzyme - 测试 `componentDidMount` 异步调用

javascript - jQuery 计算插件 - 需要简单的建议

javascript - Jquery Div 从右到左的幻灯片转换无法正常工作

html - 使用动态设置的颜色来响应 <hr/>