<Button
    onClick={() => {
        console.log('addedNodes', addedNodes)
        let credentials = //something...
        let nodes = [...addedNodes]
        console.log(addedNodes)
        setCurrentForm(
            {
                ...currentForm,
                credentials: credentials,
                nodes: [...addedNodes],
            }
        )
    }}
</Button>


我有一个使用其他状态currentForm更新addedNodes状态的按钮。
每当currentForm更新时,我都会使用currentForm console.log useEffect

useEffect(() => {
        console.log('currentForm ,,,,,, ', currentForm)
        console.log('addedNodes ,,,,,, ', addedNodes)
    }, [currentForm]);


这会打印出正确的更新状态。

但是,当我尝试使用该状态添加API请求时,它会返回到更新前的状态。

例如,当我将useEffect更新为

useEffect(() => {
        console.log('currentForm,,,,,, ', currentForm)
        console.log('addedNodes ,,,,,, ', addedNodes)
        console.log('RUNNING POST')
        setLoadingStatus('loading')

        let body = {
            form: currentForm,
        }

        intializeForms()
        let options = {
            headers: header,
            method: 'post',
            mode: 'cors',
            body: JSON.stringify(body),
        }
        console.log('options.body', options.body)

        const urls = ['...'];
        const fetchJson = url => fetch(url, options).then(res => res.json());
        Promise.all(urls.map(fetchJson))
            .then(([result]) => {
               ...
            })
            .catch(err => {
                setLoadingStatus('none')
                console.log(err)
            });

    }, [currentForm]);


console.log('options.body', options.body)打印出旧的currentForm

这很奇怪,因为console.log(currentForm)打印期望的状态,但是当我实际将其用于API调用时,它又回到了原始形式。

我认为这是因为每次状态更新时都会调用此useEffect,但不是很确定。

有什么帮助吗?

最佳答案

有问题的代码片段


    let body = {
        form: currentForm,
    }
    intializeForms()
    // later bad body.form content



form获取对currentFrom对象的引用,然后currentFromintializeForms()中被覆盖...这样,JSON.stringify(body)对错误数据进行操作。

为什么Kaca992的解决方案不起作用?


let body = {
    form: {...currentForm},
  }



它应该从currentForm'元素/属性创建一个新对象。
可能它对currentForm的某些部分有效,例如对于nodes,因为它们已正确分配(通过不可变的方式-通过新实例):

 nodes: [...addedNodes],


可能其他currentForm元素是始终相同的对象引用的副本,这些对象引用在更改时发生了变异,而不是被新实例替换。

解:

在这种情况下,只要在intializeForms()“消费”(字符串化)-currentForm块之后调用let options =就足够了。

表单重置(intializeForms()调用)的其他好地方可以是Promise.all(...解析功能(.then部分)。

08-06 10:13