我有这个组件和下面的界面
interface IProps {
data: Array<{
low: number,
high: number,
open: number,
close: number,
openTime: number
}>
}
const Canvas: React.FC<IProps> = (props) => {
const [data, setData] = useState<Array<{
low: number,
high: number,
open: number,
close: number,
openTime: number
}>>();
}
useEffect(() => {
setData(props.data)
}, []) //warning1
useEffect(() => {
const canvas: any = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (data) {
setCandleWidth(canvas.width / data.length)
}
}, [data && data.length != 0]) //Warning2
}
而且两个 useEffect 都在给我警告
第一个是这样的,因为我使用它就好像它是一个 componentDidMount() ,但它说
<块引用>React Hook useEffect 缺少依赖项:'props.data'。任何一个 包括它或删除依赖数组。如果“setData”需要 'props.data'的当前值,你也可以切换到useReducer 而不是 useState 并在 reducer 中读取“props.data”。
第二个说的是以下内容,而我只是想在设置数据后触发它
<块引用>React Hook useEffect 缺少依赖项:'data'。要么包括 它或删除依赖项 array.eslintreact-hooks/exhaustive-deps React Hook useEffect 在依赖数组中有一个复杂的表达式。 将其提取到一个单独的变量中,以便它可以是静态的 已检查.eslintreact-hooks/exhaustive-deps
那么有什么更好的方法可以做到这一点?
答案 0 :(得分:2)
这应该会有所帮助:
useEffect
并将数据直接传递给状态。useEffect
中的依赖项数组。const [data, setData] = useState(props.data);
useEffect(() => {
const canvas: any = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (data) {
setCandleWidth(canvas.width / data.length)
}
}, [data])
旁注:
通常您不想复制数据。 props.data
和 data
(状态变量)保存相同的数据。如果您选择这样做,请确保这是一个有意识的决定。
答案 1 :(得分:1)
这是因为,useEffect
只会运行一次,因为没有依赖关系,并且您只是通过在 setData
中添加 useEffect
和空数组来初始化状态(可以说) .
您应该在props.data
依赖数组中添加useEffect
,或者您可以直接使用useState
初始化数据。
const [data, setData] = useState(props.data);
// OR
useEffect(() => {
setData(props.data)
}, [props.data])
关于警告 2:
您正在计算依赖数组中的布尔值。这不会触发它重新渲染。最好在数组中添加 data
并在给定的函数内部进行检查。 useEffect
useEffect(() => {
const canvas: any = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (data && data.length != 0 {
setCandleWidth(canvas.width / data.length)
}
}, [data])
答案 2 :(得分:1)
这将解决两个警告行为没有任何改变
useEffect(() => {
setData(props.data)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
const canvas: any = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (data) {
setCandleWidth(canvas.width / data.length)
}
}, [data])
答案 3 :(得分:0)
第一个 useEffect
实际上很好。这只是一个 ESLint、TSLint 警告——那些 linter 非常不喜欢空的依赖数组。如果您绝对确定您想使用一个空数组作为依赖数组(从而使效果在初始挂载时只运行一次),您可以在该行旁边添加 ESLint disable as a comment >
至于第二个 useEffect
,你使用的依赖数组有点错误。依赖数组仅用于列出依赖项 - 即 React 将监视哪些更改;它用于列出内容,不应包含逻辑。如果你的条件渲染需要逻辑,你可以把它放在效果中,就像@Shreyas Jadhav 的回答
useEffect(() => {
const canvas: any = canvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (data && data.length != 0) {
setCandleWidth(canvas.width / data.length)
}
}, [data])
这第二个 useEffect
现在意味着,每当 data
更改时重新运行效果,但如果 setCandleWidth
不为 0,则仅 data.length