Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 反应:useState筛选器数组未更新状态_Reactjs_Typescript_React Hooks - Fatal编程技术网

Reactjs 反应:useState筛选器数组未更新状态

Reactjs 反应:useState筛选器数组未更新状态,reactjs,typescript,react-hooks,Reactjs,Typescript,React Hooks,编辑: 发生错误是因为我将数组作为第二个参数传递给了useffect。即使数组中的值保持不变,引用也会不断更改,因此会不断调用useffect,并重置我的复选框值。该数组是通过调用useState创建的。我将useState替换为useReducer(如果对象实际发生了更改,reducer只会更改对象引用),并更新了组件树更高层次上缺少的一些依赖项 原始问题: 我无法更新功能组件中的状态 我的问题有点类似于这个: 我已经在复制我的状态对象(通过使用array.filter)而不是引用它;但我的

编辑:

发生错误是因为我将数组作为第二个参数传递给了
useffect
。即使数组中的值保持不变,引用也会不断更改,因此会不断调用
useffect
,并重置我的复选框值。该数组是通过调用
useState
创建的。我将
useState
替换为
useReducer
(如果对象实际发生了更改,reducer只会更改对象引用),并更新了组件树更高层次上缺少的一些依赖项

原始问题:

我无法更新功能组件中的状态

我的问题有点类似于这个:

我已经在复制我的状态对象(通过使用array.filter)而不是引用它;但我的状态仍然没有更新

为了追踪问题,我尝试用一个简单的例子重新创建问题:

但在我最简单的例子中,一切都按预期进行。我无法重现这个错误

以下是状态不更新的示例:

configCheckboxGroup.tsx:

import classNames from "classnames";
import React, { useState, useEffect } from "react";
import { Component } from "../../model";
import CheckboxPanel from "./panels/checkboxPanel";

interface configCheckboxGroupProps {
    className?: string;
    choices: Array<Component>;
    selected: Array<string>;
    addToCart: (items: Array<Component>) => void;
}

const ConfigCheckboxGroup: React.SFC<configCheckboxGroupProps> = ({
    className,
    choices,
    selected,
    addToCart,
}) => {

    const [ selectedComp, setSelectedComp ] = useState<Array<string>>(selected);

    // device loads later, selected has to be updated
    useEffect(() => {
        setSelectedComp(selected);
    }, [selected]);

    const handleOnChange = (ev: React.FormEvent, id: string) => {
        console.debug(id);
        console.debug(selectedComp.filter(el => el !== id));
        if (selectedComp.includes(id)) {
            // was already checked || this line is not working!
            setSelectedComp(selectedComp.filter(el => el !== id));
        } else {
            // was not checked
            setSelectedComp([...(selectedComp), id]);
        }

        const selected = choices.filter(el => selectedComp.includes(el.reference._id));
        addToCart(selected);        
    };

    return (
        <div className={classNames("panellist", className)}>
        {
            choices.map(el => {
                return (
                    <CheckboxPanel 
                        image={ el.reference.picture ? el.reference.picture : undefined }
                        name={ el.reference.name }
                        id={ el.reference._id }
                        price={ el.reference.price ? el.reference.price : 
                            el.price ? el.price : 0 } 
                        key={ el._id }
                        checked={ selectedComp.includes(el.reference._id) }  
                        onChange={ handleOnChange }
                    />
                )
            })
        }
        <span>
        { selectedComp }
            </span>
            </div>
    )
}

export default ConfigCheckboxGroup;
从“classNames”导入类名;
从“React”导入React,{useState,useffect};
从“../../model”导入{Component};
从“/panels/CheckboxPanel”导入CheckboxPanel;
接口configCheckboxGroupProps{
类名?:字符串;
选择:数组;
所选:阵列;
addToCart:(项目:数组)=>无效;
}
const ConfigCheckboxGroup:React.SFC=({
类名,
选择,
挑选出来的,
addToCart,
}) => {
const[selectedComp,setSelectedComp]=使用状态(已选择);
//设备加载之后,必须更新所选设备
useffect(()=>{
设置选择的补偿(已选择);
},[选定];
const handleOnChange=(ev:React.FormEvent,id:string)=>{
console.debug(id);
调试(selectedComp.filter(el=>el!==id));
如果(所选公司包括(id)){
//已检查| |此线路不工作!
设置selectedComp(selectedComp.filter(el=>el!==id));
}否则{
//没有检查
设置selectedComp([…(selectedComp),id]);
}
const selected=choices.filter(el=>selectedComp.includes(el.reference.\u id));
addToCart(选定);
};
返回(
{
choices.map(el=>{
返回(
)
})
}
{selectedComp}
)
}
导出默认ConfigCheckboxGroup;
和checkboxPanel.tsx:

import classNames from "classnames";
import React from "react";

import "./checkboxPanel.scss";

import noImage from "../../../resources/images/errors/no-image.svg";

interface PanelProps {
    className?: string;
    image?: string;
    name: string;
    id: string;
    price: number;
    checked: boolean;
    onChange: (ev: React.FormEvent, id: string) => void;
}

const CheckboxPanel: React.SFC<PanelProps> = ({
    className,
    image,
    name,
    id,
    price,
    checked,
    onChange,
}) => {

    const getImage = () => {
        if (image) {
            return image;
        } else {
            return noImage;
        }
    }

    return (
        <div className={classNames("panel", "checkbox-panel", className)}>
            <div className="top">
                <div className="image">
                    <img alt="Product" src={getImage()} />
                </div>
                <div className="name">
                    {name}
                </div>
            </div>
            <div className="bottom">
                <div className="category">
                    { Number(price).toFixed(2) } €
                </div>
                <div>
                    <input type="checkbox" 
                        checked={ checked }
                        onChange={ (e) => onChange(e, id) }
                    />                    
                </div>
            </div>
        </div>
    )

};

export default CheckboxPanel;
从“classNames”导入类名;
从“React”导入React;
导入“/checkboxPanel.scss”;
从“../../resources/images/errors/no image.svg”导入noImage;
接口面板道具{
类名?:字符串;
图像?:字符串;
名称:字符串;
id:字符串;
价格:数量;
选中:布尔值;
onChange:(ev:React.FormEvent,id:string)=>void;
}
const CheckboxPanel:React.SFC=({
类名,
形象,,
名称
身份证件
价格,
选中的,
一旦改变,
}) => {
常量getImage=()=>{
如果(图像){
返回图像;
}否则{
返回noImage;
}
}
返回(
{name}
{编号(价格).toFixed(2)}€
onChange(e,id)}
/>                    
)
};
导出默认复选框面板;
两个示例之间的唯一区别是,在第二个示例中,我在子组件中调用handle函数。但我在其他场合也做了同样的事情:我有一个非常类似的组件configRadioGroup,它带有单选按钮,而不是复选框,在那里一切正常


我试着通过手动过滤数组和尝试许多其他方法来进行游戏,但似乎没有任何帮助。这就是为什么,作为最后一次尝试,我在这里问(虽然我知道这个问题不是一个好问题,因为它非常具体)。

更改属性
selected
将重置
selectedComp
如果您在useEffect中放置一个控制台日志,您可能会发现每次都会重置它

您需要跟踪所选内容的来源(redux?)以及设置方式(addToCart?)

脏修复程序可能仅在安装组件时设置
selectedComp
,这是脏的,将/应该导致react hooks/deps lint触发:

useEffect(() => {
  setSelectedComp(selected);
}, []);

但最好能找到所选
的问题所在
,如果它来自redux,那么可能只是使用
selected
,而忘记
selectedComp
,因为它只是一个副本。

更改属性
selected
将重置
selectedComp
如果您将控制台日志放在useEffect中,您可能会发现每次都会重置它。您是对的!虽然我不知道为什么它会重置<代码>所选仅应在加载我的数据并设置默认状态时更新一次。我想我还得进一步追查,但你还是解决了我的问题(我甚至没有想到
useffect
line);如果您将其作为答案发布,我将接受。我认为
selected
是一个数组或对象(参考值)而不是字符串(原语值),并且
selected
由reducer或任何
addToCart
引起的更改。您是对的,如果在JS
{}中选择的
未更改,则不会调用useffect=={}
意味着
{}
不等于
{}
,因为它是一个不同的引用。你应该从源头上解决这个问题,我怀疑这是