#reactjs #react-hooks #react-functional-component #react-class-based-component
#reactjs #реагирующие крючки #реагирующий функциональный компонент #реагирующий компонент на основе класса
Вопрос:
Я пытаюсь преобразовать компонент класса в функциональный компонент.
Компонент класса: classBasedComponent.js [Исходный код, включенный в этот файл]
Прогресс, достигнутый мной:
Функциональный компонент: functionComponent.js [Мой прогресс]
Вот ссылка на GitHub для справки: https://github.com/codebushi/gatsby-starter-dimension
Вот мои ошибки:
- 12:19 предупреждение «setArticle» присваивается значение, но никогда не используется no-unused-vars
- 27:11 ошибка ‘timeoutId’ не определен no-undef
- 33:6 предупреждение У useEffect с реактивным хуком отсутствует зависимость: ‘handleClickOutside’. Либо включите его, либо удалите массив зависимостей react-hooks / исчерпывающий-deps
- 45:30 ошибка ‘setWrapperRef’ не определена no-undef
- 58:37 Ожидаемое предупреждение ‘===’ и вместо этого увидел ‘==’ eqeqeq
- 66:23 ошибка Неожиданного использования ‘location’ без ограничений-globals
- 80:28 ошибка ‘setWrapperRef’ не определена no-undef
Я все еще получаю ошибки с этим. Где я могу импровизировать?
Ответ №1:
Давайте сосредоточимся на ошибках.
27:11 ошибка ‘timeoutId’ не определен no-undef
Вы объявили эту переменную как timeoutId
, но переключаетесь между timeoutId
и timeOutId
при обращении к ней. В вашей текущей изолированной среде это так timeoutId
, поэтому все timeOutId
способы использования помечены как необъявленные. Остановитесь на одном или другом и будьте последовательны.
45:30 ошибка ‘setWrapperRef’ не определена no-undef
и
80:28 ошибка ‘setWrapperRef’ не определена no-undef
Похоже, это функция, вызываемая Main
для передачи ссылки на что-то, на что затем ссылаются handleClickOutside
. Используйте ref react для сохранения значения.
const wrapperRef = React.useRef(null); // create ref to store value
...
const setWrapperRef = node => wrapperRef.current = node; // set current ref value
...
const handleClickOutside = (event) => {
if (!wrapperRef.current.contains(event.target)) { // access current ref value
if (isArticleVisible) {
handleCloseArticle();
}
}
}
...
<Main
isArticleVisible={isArticleVisible}
timeout={timeout}
articleTimeout={articleTimeout}
article={article}
onCloseArticle={handleCloseArticle}
setWrapperRef={setWrapperRef} // attach ref value updater
/>
66:23 ошибка Неожиданного использования ‘location’ без ограничений-globals
location
ранее был получен через props
, вероятно, он все еще получен через props
.
<Layout location={props.location}>
Или, поскольку я не вижу других ссылок props
на ваш функциональный компонент, просто уничтожьте его в подписи компонента. Если вам нужно получить доступ к большему количеству значений prop, вы можете просто также уничтожить их здесь.
function IndexPage({ location }) { ...
И теперь предупреждения
12:19 предупреждение «setArticle» присваивается значение, но никогда не используется no-unused-vars
Это просто означает, что он был определен и никогда не использовался, но после проверки компонента на основе класса обновление article
значения происходит в handleOpenArticle
и handleCloseArticle
. Итак, давайте сделаем то же самое в вашем функциональном компоненте.
Проблема здесь заключалась в том, что вы передавали setIsArticleVisible
программе обновления дополнительные аргументы, которые игнорировались. useState
программы обновления не объединяют обновления неглубоко, а ваши объявлены содержащими только одно значение. Я предлагаю также использовать обновление функционального состояния для переключения значений логического состояния.
handleOpenArticle(article) {
this.setState({
isArticleVisible: !this.state.isArticleVisible,
article
});
setTimeout(() => {
this.setState({
timeout: !this.state.timeout
});
}, 325);
setTimeout(() => {
this.setState({
articleTimeout: !this.state.articleTimeout
});
}, 350);
}
handleCloseArticle() {
this.setState({
articleTimeout: !this.state.articleTimeout
});
setTimeout(() => {
this.setState({
timeout: !this.state.timeout
});
}, 325);
setTimeout(() => {
this.setState({
isArticleVisible: !this.state.isArticleVisible,
article: ""
});
}, 350);
}
становится
const handleOpenArticle = (article) => {
setIsArticleVisible(isArticleVisible => !isArticleVisible);
setArticle(article);
setTimeout(() => setTimeout(timeout => !timeout), 325);
setTimeout(() => setArticleTimeout(articleTimeout => !articleTimeout), 350);
};
const handleCloseArticle = (article) => {
setArticleTimeout(articleTimeout => !articleTimeout);
setTimeout(() => setTimeout(timeout => !timeout), 325);
setTimeout(() => {
setIsArticleVisible(isArticleVisible => !isArticleVisible);
setArticle("");
}, 350);
};
33:6 предупреждение О том, что useEffect реагирует на хук, имеет отсутствующую зависимость:
‘handleClickOutside’. Либо включите его, либо удалите массив зависимостей
react-hooks / исчерпывающий-deps
Обычно вы хотели бы включить все зависимости для эффекта, чтобы все значения были правильными, но здесь ясно, что намерение состоит в том, чтобы добавить слушателей при монтировании компонента и удалить их при размонтировании. Вы можете добавить eslint-disable
комментарий только для этой строки. Я предлагаю также переместить timeoutId
timeOutId
объявление / внутри эффекта, поскольку оно не используется вне его. Также безопасно переходить undefined
к clearTimeout
нему, он может справиться с этим, поэтому удалите условную проверку.
useEffect(() => {
const timeoutId = setTimeout(() => {
setLoading("");
}, 100);
document.addEventListener("mousedown", handleClickOutside);
return () => {
clearTimeout(timeoutId);
document.removeEventListener("mousedown", handleClickOutside);
};
// Effect triggered on component mount only
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
58:37 Ожидаемое предупреждение ‘===’ и вместо этого увидел ‘==’ eqeqeq
Не уверен, откуда взялась эта логика, но она заменена wrapperRef
исправлением ошибки выше.
Примечание:
Все вышеприведенные предложения полностью основаны на ваших самоописанных / сообщенных проблемах и на том, что я мог видеть помеченным в вашей изолированной среде. После их устранения могут возникнуть другие потенциальные проблемы (возможно, потому, что они были замаскированы ими.
Комментарии:
1. Я получаю последующую ошибку: ошибка: превышена максимальная глубина обновления. Это может произойти, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate . React ограничивает количество вложенных обновлений, чтобы предотвратить бесконечные циклы. Эта ошибка, по-видимому, вызвана эффектом использования.
2. Я использую article в качестве опоры. Я использую кнопку с кодом: <кнопка onClick={props.onOpenArticle(‘id’)}>Работает</button> в другом файле. Это вызывает бесконечные циклы.
3. @KillMe Есть ли у этой новой ошибки трассировка стека? Можете ли вы сказать, какой компонент вызывает ошибку? В
IndexPage
компоненте в вашем codesandbox состояниеuseEffect
не устанавливается безоговорочно и не имеет зависимостей, поэтому оно не будет повторно запускаться при последующих рендерингах.4. @KillMe Ах, можете ли вы тогда поделиться этим другим файлом и деталями ошибки в своем вопросе?
5. Вот файл: codesandbox.io/s/dreamy-flower-1vkuc?file=/src/header.js