Javascript 状态不会用React钩子更新

Javascript 状态不会用React钩子更新,javascript,reactjs,closures,react-hooks,Javascript,Reactjs,Closures,React Hooks,我以为我的头被钩子钩住了。然而,我正在努力解决这个问题。下面的代码是我实际演示代码的一个非常简化的版本。实际上,clickHandler()和upload()要复杂得多。这就是为什么不能将它们组合成一个函数的原因。问题是我无法从upload函数中的状态访问更新的文件数组。但是,如果我对数组使用ref,它就会工作,我认为它是一个反模式。我还试图在组件外部声明状态,但没有成功。谢谢你的帮助 import React, { useCallback, useState } from 'react';

我以为我的头被钩子钩住了。然而,我正在努力解决这个问题。下面的代码是我实际演示代码的一个非常简化的版本。实际上,
clickHandler()
upload()
要复杂得多。这就是为什么不能将它们组合成一个函数的原因。问题是我无法从upload函数中的状态访问更新的文件数组。但是,如果我对数组使用ref,它就会工作,我认为它是一个反模式。我还试图在组件外部声明状态,但没有成功。谢谢你的帮助

import React, { useCallback, useState } from 'react';

const HomeScreen = () => {

    const initialState = {
        error: false,
        files: [],
        totalSize: 0,
        finished: false
    };

    const [state, setState] = useState(initialState);

    const upload = useCallback(() => {
        // At this point state.files is an empty array
        console.log(state.files);
    }, [state]);

    const clickHandler = useCallback(() => {
        const queue = [
            { id: 1, bool: false },
            { id: 2, bool: false }
        ];

        setState((state) => {
            return { ...state, files: queue }
        });

        upload()

    }, [upload]);

    return <button onClick={clickHandler}>Click me</button>;
};

export default HomeScreen;
import React,{useCallback,useState}来自“React”;
常量主屏幕=()=>{
常量初始状态={
错误:false,
文件:[],
总大小:0,
完成:错误
};
常量[状态,设置状态]=使用状态(初始状态);
const upload=useCallback(()=>{
//此时state.files是一个空数组
console.log(state.files);
},[州];
常量clickHandler=useCallback(()=>{
常量队列=[
{id:1,bool:false},
{id:2,bool:false}
];
设置状态((状态)=>{
返回{…状态,文件:队列}
});
上传()
},[上传];
返回点击我;
};
导出默认主屏幕;

使用钩子状态更新程序进行状态更新是异步的,因此当您从
clickHandler
中调用upload时,更新的状态对您不可用。将状态传递给upload方法的最简单解决方案

import React, { useCallback, useState } from 'react';

const HomeScreen = () => {

    const initialState = {
        error: false,
        files: [],
        totalSize: 0,
        finished: false
    };

    const [state, setState] = useState(initialState);

    const upload = useCallback((updatedState) => {
        // At this point state.files is an empty array
        console.log((updatedState || state).files);
    }, [state]);

    const clickHandler = useCallback(() => {
        const queue = [
            { id: 1, bool: false },
            { id: 2, bool: false }
        ];

        setState((state) => {
            const updatedState = { ...state, files: queue }
            upload(updatedState )
            return updatedState;
        });

        upload()

    }, [upload]);

    return <button onClick={clickHandler}>Click me</button>;
};

export default HomeScreen;
import React,{useCallback,useState}来自“React”;
常量主屏幕=()=>{
常量初始状态={
错误:false,
文件:[],
总大小:0,
完成:错误
};
常量[状态,设置状态]=使用状态(初始状态);
const upload=useCallback((updatedState)=>{
//此时state.files是一个空数组
log((updatedState | | state).files);
},[州];
常量clickHandler=useCallback(()=>{
常量队列=[
{id:1,bool:false},
{id:2,bool:false}
];
设置状态((状态)=>{
const updatedState={…状态,文件:队列}
上载(updatedState)
返回updatestate;
});
上传()
},[上传];
返回点击我;
};
导出默认主屏幕;

使用钩子状态更新程序进行状态更新是异步的,因此当您从
clickHandler
中调用upload时,更新的状态对您不可用。将状态传递给upload方法的最简单解决方案

import React, { useCallback, useState } from 'react';

const HomeScreen = () => {

    const initialState = {
        error: false,
        files: [],
        totalSize: 0,
        finished: false
    };

    const [state, setState] = useState(initialState);

    const upload = useCallback((updatedState) => {
        // At this point state.files is an empty array
        console.log((updatedState || state).files);
    }, [state]);

    const clickHandler = useCallback(() => {
        const queue = [
            { id: 1, bool: false },
            { id: 2, bool: false }
        ];

        setState((state) => {
            const updatedState = { ...state, files: queue }
            upload(updatedState )
            return updatedState;
        });

        upload()

    }, [upload]);

    return <button onClick={clickHandler}>Click me</button>;
};

export default HomeScreen;
import React,{useCallback,useState}来自“React”;
常量主屏幕=()=>{
常量初始状态={
错误:false,
文件:[],
总大小:0,
完成:错误
};
常量[状态,设置状态]=使用状态(初始状态);
const upload=useCallback((updatedState)=>{
//此时state.files是一个空数组
log((updatedState | | state).files);
},[州];
常量clickHandler=useCallback(()=>{
常量队列=[
{id:1,bool:false},
{id:2,bool:false}
];
设置状态((状态)=>{
const updatedState={…状态,文件:队列}
上载(updatedState)
返回updatestate;
});
上传()
},[上传];
返回点击我;
};
导出默认主屏幕;
要使您的
upload()
函数能够访问当前状态,必须从
useffect()
调用该函数。看看这对你有用吗

const主屏幕=()=>{
常量初始状态={
错误:false,
文件:[],
总大小:0,
完成:错误
};
const[state,setState]=React.useState(initialState);
const upload=React.useCallback(()=>{
//此时state.files是一个空数组
console.log(state.files);
},[州];
React.useffect(()=>{
state.files.length?upload():null;
},[州];
const clickHandler=React.useCallback(()=>{
常量队列=[
{id:1,bool:false},
{id:2,bool:false}
];
设置状态((状态)=>{
返回{…状态,文件:队列}
});
//上传()
},[上传];
返回点击我;
};
ReactDOM.render(,document.getElementById('root'))

要使您的
upload()
函数能够访问当前状态,必须从
useffect()
调用该函数。看看这对你有用吗

const主屏幕=()=>{
常量初始状态={
错误:false,
文件:[],
总大小:0,
完成:错误
};
const[state,setState]=React.useState(initialState);
const upload=React.useCallback(()=>{
//此时state.files是一个空数组
console.log(state.files);
},[州];
React.useffect(()=>{
state.files.length?upload():null;
},[州];
const clickHandler=React.useCallback(()=>{
常量队列=[
{id:1,bool:false},
{id:2,bool:false}
];
设置状态((状态)=>{
返回{…状态,文件:队列}
});
//上传()
},[上传];
返回点击我;
};
ReactDOM.render(,document.getElementById('root'))


感谢您的快速回答。我也考虑过这一点,并尝试添加一些超时,但也不起作用。你能解释一下原因吗?这是因为setTimeout函数中有一个新的闭包吗?谢谢你的快速回答。我也考虑过这一点,并尝试添加一些超时,但也不起作用。你能解释一下原因吗?是因为setTimeout函数中有一个新的闭包吗?