useState对象的值始终是初始值

时间:2019-12-06 20:20:06

标签: javascript reactjs react-hooks

我有代码,如果调用一个函数,它将调用toggleCheckedUser并传递有关要切换哪个对象属性的信息。然后将修改后的对象保存回状态(selectedSendTo)。

但是,当我运行此命令时,切换起作用了,但是当我尝试编辑第二个属性时,在更改它之前,我尝试console.log(selectedSendTo)总是获得初始值,无论它是空对象{{1 }}或{}代替以前更新的对象。

当我使用false监视useEffect时,可以看到selectedSendTo函数正确地更新了对象。因此由于某种原因,当我重新访问该对象时,它是空的。

setSelectedSendTo()
const [selectedSendTo, setSelectedSendTo] = useState(false);

这是DOM:

const toggleCheckedUser = (companyID, contactID) => {
    console.log(companyID, contactID); 
    console.log(selectedSendTo); // THIS VALUE IS always the same as INITIAL value
    console.log(selectedSendTo[companyID]);
    if(selectedSendTo[companyID] && 
        selectedSendTo[companyID][contactID] === true){
            //remove it
            delete(selectedSendTo[companyID][contactID]);
    }else{
        setSelectedSendTo({
            ...selectedSendTo,
            [companyID]:{
                ...selectedSendTo[companyID],
                [contactID]: true,
            }
        })
    }
}

更新,一种可能的解决方案

我发现以下工作有效:

为了能够从<CustomCheckbox className="person__checkbox" name={`checkbox-${contactID}`} alreadySelected={ selectedSendTo[company.companyID] && selectedSendTo[company.companyID][contactID] } onChange={() => toggleCheckedUser(company.companyID, contactID)} /> 访问当前值,我使用了useState

useRef
const selectedSendToRef = useRef();

然后在函数内,我可以使用useEffect( () => { selectedSendToRef.current = selectedSendTo; }, [selectedSendTo]) 访问`selectedSendTo的最新值。

更新状态时,我可以使用

从状态访问最新版本

selectedSendToRef.current

setSelectedSendTo( prevValue => ....)

更新2:真正的解决方案

好的,看来问题在于即使在渲染之后,子组件也由于我如何使用嵌套函数创建元素而没有收到更新状态。

这是我的生活方式

const toggleCheckedUser = (companyID, contactID) => {
    console.log(companyID, contactID, selectedSendToRef.current);
    console.log('selectedSendTo[companyID]: ', selectedSendTo[companyID]);

    let newValue; 
    if(selectedSendToRef.current[companyID] && 
        selectedSendToRef.current[companyID][contactID] === true){
        newValue = false;
    }else{
        newValue = true;
    }
    setSelectedSendTo(prevValue => (
        {
            ...prevValue,
            [companyID]:{
                ...prevValue[companyID],
                [contactID]: newValue,
            }
        }
    ));
}

<Main Component> <div> {Object_1} <div> </Main Componenent 的定义如下:

object_1

现在要创建添加我想显示的元素的状态对象,我正在使用一个由useEffect钩子调用的函数。基本上,当服务器发回我需要的数据时,我会告诉const Object_1 = <React.Fragment> <h1>Random Header</h1> {StateObject_Containg_Elements} </React.Fragment> 钩子运行一个名为useEffect

的函数。
createElements

如您所见,我们基本上有一个运行1次(在服务器响应时)的函数,该函数触发一个函数,该函数创建我们要显示的元素数组,该数组具有自己的嵌套子函数,其中包括我们所要的子组件要求观看另一个状态对象以了解是否应该检查它。

所以我所做的就是简化事情,我将const createElements = (data) => { const elements = Object.keys(data).map( item => return( <ul> {subFunction1(item)} </ul> subFunction1(item){ item.contacts.map( name => { reutrn <CustomCheckbox name={name} checked={selectedSendTo[name]} }) } saveElementsToState(elements); } 变成了它自己的功能组件,我们称之为{Object_1}。在组件内部而不是调用函数,我只是将函数代码放入其中以循环遍历并返回元素(不再将元素保存到状态),最后我不再需要useEffect,因为只用一次数据更新状态对象即可从服务器获取它会导致我的子组件重新渲染并创建元素。在子组件内部,如果状态为null的数据我只是返回null。

那解决了我所有的问题。

所以现在看起来类似

<Object1 />

0 个答案:

没有答案