Reactjs 反应本机-反应挂钩:警告:Can';t在未安装的组件上执行React状态更新

Reactjs 反应本机-反应挂钩:警告:Can';t在未安装的组件上执行React状态更新,reactjs,react-native,react-hooks,Reactjs,React Native,React Hooks,当我多次单击+1按钮时,请稍等片刻,然后再次单击几次,将显示错误消息: “index.js:1警告:无法对未安装的组件执行React状态更新。这是一个no op,但表示应用程序内存泄漏。若要修复,请取消useEffect清理函数中的所有订阅和异步任务。”。 在图像中(Test.js:31) 在Imagecomponent中(Test.js:41)” 但是如果我删除Imagecomponent,错误就会消失,我希望保持这个程序的结构,如果可能的话,尽量使图像不闪烁 import React, {

当我多次单击
+1按钮
时,请稍等片刻,然后再次单击几次,将显示错误消息:

“index.js:1警告:无法对未安装的组件执行React状态更新。这是一个no op,但表示应用程序内存泄漏。若要修复,请取消useEffect清理函数中的所有订阅和异步任务。”。 在图像中(Test.js:31) 在Imagecomponent中(Test.js:41)”

但是如果我删除
Imagecomponent
,错误就会消失,我希望保持这个程序的结构,如果可能的话,尽量使图像不闪烁

import React, { useState, useEffect } from 'react';
import { TouchableHighlight, Text, Image } from 'react-native';

export default function Test() {
    const imagePath = require('./assets/image.png')
    const [count, setCount] = useState(0)
    const [msg, setMsg] = useState("")
    useEffect(()=>{
        changeMsg()
    },[count])

    const changeMsg=()=>{
        let temp = 0
        for(let i = 0; i < 1000000000; i++){
            temp += 1
        }
        let newMsg = "newMsg = " + count
        setMsg(newMsg)
    }
    const Imagecomponent=()=>{
        return(
            <>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            </>
        )
    }

    return(
        <>
        <TouchableHighlight onPress={()=>{setCount(count+1)}}><Text>+1</Text></TouchableHighlight>
        <Text>{msg}</Text>
        <Imagecomponent/>
        </>
    )
}
import React,{useState,useffect}来自“React”;
从“react native”导入{TouchableHighlight,Text,Image};
导出默认函数测试(){
const imagePath=require('./assets/image.png')
const[count,setCount]=useState(0)
const[msg,setMsg]=useState(“”)
useffect(()=>{
changeMsg()
},[计数])
constchangemsg=()=>{
设温度=0
对于(设i=0;i<100000000;i++){
温度+=1
}
让newMsg=“newMsg=”+计数
setMsg(newMsg)
}
常量Imagecomponent=()=>{
返回(
)
}
返回(
{setCount(count+1)}>+1
{msg}
)
}

您错误地使用了useEffect。此钩子用于异步操作,例如执行Ajax请求。但在这里,您是同步使用它的,您所做的唯一操作是更新消息的状态。因此,每次单击都会渲染两次,一次用于计数更新,另一次用于消息更新

错误的原因是您阻塞主线程的时间太长,react会触发超时

如果您只想显示单击次数,则更容易:

import React, { useState } from 'react';
import { TouchableHighlight, Text, Image } from 'react-native';

const Imagecomponent=()=>{
    return(
        <>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
        </>
    )
}

export default function Test() {
    const imagePath = require('./assets/image.png')
    const [count, setCount] = useState(0)

    let message = `newMsg ${count}`

    return(
        <>
            <TouchableHighlight onPress={()=>{setCount(count+1)}}><Text>+1</Text></TouchableHighlight>
            <Text>{message}</Text>
            <Imagecomponent/>
        </>
    )
}
import React,{useState}来自“React”;
从“react native”导入{TouchableHighlight,Text,Image};
常量Imagecomponent=()=>{
返回(
)
}
导出默认函数测试(){
const imagePath=require('./assets/image.png')
const[count,setCount]=useState(0)
let message=`newMsg${count}`
返回(
{setCount(count+1)}>+1
{message}
)
}

我将ImageComponent移出了render函数,因为您在每次渲染时都“重新声明”了该组件,所以您永远不应该在渲染函数中声明组件。

您使用useEffect的方法是错误的。此钩子用于异步操作,例如执行Ajax请求。但在这里,您是同步使用它的,您所做的唯一操作是更新消息的状态。因此,每次单击都会渲染两次,一次用于计数更新,另一次用于消息更新

错误的原因是您阻塞主线程的时间太长,react会触发超时

如果您只想显示单击次数,则更容易:

import React, { useState } from 'react';
import { TouchableHighlight, Text, Image } from 'react-native';

const Imagecomponent=()=>{
    return(
        <>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
            <Image style={{height: 40, width: 40}} source={imagePath}></Image>
        </>
    )
}

export default function Test() {
    const imagePath = require('./assets/image.png')
    const [count, setCount] = useState(0)

    let message = `newMsg ${count}`

    return(
        <>
            <TouchableHighlight onPress={()=>{setCount(count+1)}}><Text>+1</Text></TouchableHighlight>
            <Text>{message}</Text>
            <Imagecomponent/>
        </>
    )
}
import React,{useState}来自“React”;
从“react native”导入{TouchableHighlight,Text,Image};
常量Imagecomponent=()=>{
返回(
)
}
导出默认函数测试(){
const imagePath=require('./assets/image.png')
const[count,setCount]=useState(0)
let message=`newMsg${count}`
返回(
{setCount(count+1)}>+1
{message}
)
}

我将ImageComponent移出了render函数,因为您在每次渲染时都要“重新声明”此组件,所以您不应该在render函数中声明组件。

for loop inside changeMsg function的目的是什么?@J.Doe只是为了创建一个需要一些时间才能运行的函数,这只是我的另一个程序的一个简单版本,原始函数确实需要一些时间进行一些计算task@GGprogram如果要创建延迟,最好使用window.setTimeout,否则会阻塞主线程,无法实现什么?是否要显示单击次数?因为你可以做得更简单,你根本不需要使用useEffect。@Manjar我想做的是:onClick=>setCount+1并调用一个计算函数,计算函数将使用count作为输入,因此,我只是使用了计算函数,因此每次调用该函数时,都会使用最新的计数值changeMsg函数中for循环的用途是什么?@J.Doe只是为了创建一个需要一些时间才能运行的函数,这只是我的另一个程序的简单版本,原始函数确实需要一些时间进行一些计算task@GGprogram如果要创建延迟,最好使用window.setTimeout,否则会阻塞主线程,无法实现什么?是否要显示单击次数?因为你可以做得更简单,你根本不需要使用useEffect。@Manjar我想做的是:onClick=>setCount+1并调用一个计算函数,计算函数将使用count作为输入,所以我只是将计算函数置于useEffect中,以便每次调用该函数时都使用最新的计数值