Я зарылся в глубокую кроличью нору с этим компонентом, пытаясь использовать React-хуки.
Родительский компонент обрабатывает состояние dictionary
, которое в конечном итоге распределяется между несколькими компонентами.
Мой проблемный дочерний компонент WordInput
имеет форму с одним входом. При отправке формы компонент извлекает определение слова из API и передает родительское слово и определение, которое затем устанавливает состояние в виде dictionary
. Пока все хорошо, ЕСЛИ это первое слово в dictionary
. Часть, с которой у меня возникают проблемы, состоит в том, чтобы представить любые последующие слова / определения.
Когда пользователь отправляет последующее слово, я хочу, чтобы компонент проверил, существует ли слово в dictionary
, которое передается потомку. Если он не существует, добавьте его в dictionary
через функцию отправки.
Я думаю, проблема в том, что я пытаюсь сделать слишком много с useEffect
I useEffect
, чтобы: - установить загрузку - проверить и обработать словарь для существующих слов - проверить определение и слово aren ' t пусто и отправить оба в parent / dictionary - получить определение из API
. В необработанном коде у меня есть несколько console.groups
, чтобы помочь мне отслеживать происходящее. Чем больше я добавляю к компоненту, тем больше накапливается подгрупп и подгрупп подгрупп. Ясно, что подход, который я использую, не очень dry и вызывает слишком много повторных рендеринг функций component / useEffect. Для краткости я вынул console.log
записей.
Импортированный fetchWordDefinition
просто обрабатывает извлеченные данные и правильно упорядочивает их в массив.
Я не знаю, как оставьте это dry и эффективным, и любая помощь оценена с этой довольно простой задачей. Моя догадка - сохранить все логики c для отправки слова / определения в обработчике отправки и использовать только 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;