正在收到此警告:
无法在未安装的组件上执行React状态更新。这是无人...
它是由child component
引起的,我不知道如何消除它。
请注意,我已经阅读了许多其他文章,了解为什么会发生这种情况,并了解了基本问题。但是,大多数解决方案建议使用componentWillUnmount
样式的功能取消订阅(我正在使用react hooks
)
我不知道这是否表明我对React有更大的基本误会,
但实际上这是我的认识:
import React, { useEffect, useRef } from 'react';
import Picker from 'emoji-picker-react';
const MyTextarea = (props) => {
const onClick = (event, emojiObject) => {
//do stuff...
}
const isMountedRef = useRef(true);
useEffect(() => {
isMountedRef.current = true;
});
useEffect(() => {
return () => {
console.log('will unmount');
isMountedRef.current = false;
}
});
return (
<div>
<textarea></textarea>
{ isMountedRef.current ? (
<Picker onEmojiClick={onClick}/>
):null
}
</div>
);
};
export default MyTextarea;
(tl; dr)请注意:
MyTextarea
组件具有一个 parent 组件,该组件仅在特定路径上呈现。
还有一个Menu
组件,一旦单击该组件,即可根据情况更改route
和 或显示MyTextarea
的 parent 组件或显示另一个组件。
一旦我单击Menu
关闭MyTextarea
的 parent 组件,就会发生此警告。
更多上下文
state
更新。在我的情况下,我无法这样做,因为我没有设计Picker
组件(由MyTextarea
渲染)。 该警告来自此<Picker onEmojiClick={onClick}>
行,但我不想修改此现成的组件。
这说明了我基于isMountedRef
渲染组件或不渲染组件的尝试。但是,这也不起作用。发生的情况是,如果我设置了useRef(true)
,则组件将被渲染;或者,如果我建议的设置为useRef(null)
,则组件将根本不会被渲染。
答案 0 :(得分:1)
我不确定您的实际问题是什么(是您无法摆脱警告,还是<Picker>
始终呈现或永不呈现),但是我将尽力解决我看到的所有问题。
首先,您不需要根据是否安装了<Picker>
来有条件地渲染MyTextArea
。由于组件仅在挂载后才呈现,因此<Picker>
将永远不会在其所在的组件尚未挂载时呈现。
话虽如此,如果您仍然想跟踪组件何时安装,我建议您不要使用挂钩,而应将componentDidMount
和componentWillUnmount
与setState()
一起使用。这不仅使您更容易理解组件的生命周期,而且使用挂钩的方式也存在一些问题。
现在,初始化组件时,您的useRef(true)
会将isMountedRef.current
设置为true
,因此即使在安装组件之前,它也将为true。 useRef()
与componentDidMount()
不同。
在安装组件时,使用'useEffect()'将isMountedRef.current
切换为true也不起作用。尽管将在安装组件时触发,但useEffect()
的作用是副作用,而不是状态更新,因此它不会触发重新渲染,这就是为什么在设置useRef(null)
时组件从不渲染的原因
此外,您的useEffect()
钩子会在每次组件更新时触发,而不仅仅是在安装时触发,并且清理函数(返回的函数)也会在每次更新时触发,而不仅仅是在卸载时触发。因此,每次更新时,isMountedRef.current
将从true切换为false,然后又切换为true。但是,这无关紧要,因为该组件无论如何都不会重新渲染(如上所述)。
如果确实需要使用useEffect()
,则应将其组合为一个函数,并使用它来更新状态,以便触发重新渲染:
const [isMounted, setIsMounted] = useState(false); // Create state variables
useEffect(() => {
setIsMounted(true); // The effect and clean up are in one function
return () => {
console.log('will unmount');
setIsMounted(false);
}
}, [] // This prevents firing on every update, w/o it you'll get an infinite loop
);
最后,从您共享的代码来看,您的组件无法引起警告,因为代码中的任何地方都没有状态更新。您应该检查选择器的存储库中是否有问题。
编辑:似乎该警告是由您的Picker软件包引起的,https://github.com/ealush/emoji-picker-react/issues/142已经存在问题