React hook 没有在点击时更新

React hook not updating on click

我有一个名为 Np02 的反应挂钩,它显示由文件输入编辑的照片 select 并将它们保存到状态。当用户 select 的文件时,它们会以网格形式显示给他。这行得通,但有一些功能我想删除 selected 图像,但没有。函数 removeImage 运行,输出我期望的数组,但状态不会改变。我已经尝试将 setImages 移动到函数 removeImages 或其他地方,但状态本身不会改变,当我在图像上添加 useEffect 时,它仅在我 select 图像时改变,但在我想删除它们时不会改变。 为什么状态没有改变?

const MAX_IMAGES = 5;
const blankImage = 'https://static.thenounproject.com/png/187803-200.png';

function fillWithBlanks(arr) {
    const blanks = new Array(MAX_IMAGES - arr.length).fill(blankImage);
    return [...arr, ...blanks];
};

const Np02 = ({setForm}) => {

    const classes = useStyles();
    const fileInput = useRef<HTMLInputElement | null>(null);
    const dispatch = useDispatch();
    const NPData = useSelector(getNPStepData);
    const [values, setValues] = useState(NPData[1]);

    const [images, setImages] = useState<any[]>(fillWithBlanks([]));

    useEffect(() => {
        setTimeout(() => {
            setForm(checkFormValidity);
        }, 200);

    }, [values]);

    const checkFormValidity = (): boolean => {

        dispatch(submitStep(1, values));
        return true;
    };

    const imageInputChanged = (e) => {
        const files = e.target.files;
        const result: any = [];
        let fileCounter = 0;

        for (var i = 0; i < files.length; i++) {

            const file = files.item(i);

            let reader = new FileReader();
            reader.readAsDataURL(file);

            reader.onload = (e) => {

                result.push(reader.result);
                fileCounter++;

                if (fileCounter >= files.length) {
                    let uploadedImg = [...(images.filter((value) => value !== blankImage)), ...result];

                    if (MAX_IMAGES < uploadedImg.length) {
                        uploadedImg = uploadedImg.slice(uploadedImg.length - MAX_IMAGES);
                    }

                    setImages(fillWithBlanks(uploadedImg));

                }
            };
        }
    };

    const removeImage = (id) => {
        let arr = images;

        arr[id] = blankImage;
        console.log(arr); // this outputs right version of array

        return arr;
    };

    return (
        <div>
            <label htmlFor="raised-button-file" className={classes.buttonLabel}>
                <Button variant="contained" color="secondary" component="span">
                    Nahraj fotky
                </Button>
            </label>
            <FormHelperText className={classes.helperText}>Nahraj alespoň dvě různé fotky tvého
                předmětu</FormHelperText>

            <ImagesGrid images={images} imageClicked={(id) => setImages(removeImage(id))}/>

            <TextField
                className={classes.textarea}
                label="Popis"
                variant="filled"
                helperText="Zde popiš předmět, pro případné zájemce"
                multiline
                rows={6}
                value={values.desc}
                onChange={(e) => setValues({desc: e.target.value})}
            />

            <input
                ref={fileInput}
                accept="image/*"
                className={classes.input}
                id="raised-button-file"
                multiple
                type="file"
                onChange={imageInputChanged}
            />
        </div>
    );
};

export default Np02;

这是负责将图像绘制到网格的组件。

const ImagesGrid = (props: iImagesGrid) => {
    const classes = useStyles();
    const spacing = 0;

    return (
        <div className={classes.root}>
                <Grid className={classes.fullHeight} container spacing={spacing} direction="row"
                      justify="center"
                      alignItems="stretch">
                    <Grid item xs={6} onClick={() => props.imageClicked(0)}>
                        <GridImage url={props.images[0]} title={'teehee'}  />
                    </Grid>

                    <Grid item xs={6} className={classes.fullHeight}>
                        <Grid container className={classes.halfHeight} item xs={12}>
                            <Grid item xs={6}  onClick={() => props.imageClicked(1)}>
                               <GridImage url={props.images[1]} title={'teehee'}/>
                            </Grid>

                            <Grid item xs={6}  onClick={() => props.imageClicked(2)}>
                                <GridImage url={props.images[2]} title={'teehee'}/>
                            </Grid>
                        </Grid>

                        <Grid item className={classes.halfHeight} container xs={12}>
                            <Grid item xs={6}  onClick={() => props.imageClicked(3)}>
                                <GridImage url={props.images[3]} title={'teehee'}/>
                            </Grid>

                            <Grid item xs={6}  onClick={() => props.imageClicked(4)}>
                                <GridImage url={props.images[4]} title={'teehee'}/>
                            </Grid>
                        </Grid>
                    </Grid>
                </Grid>
        </div>
    );
};

export default ImagesGrid;

您正在改变这里的现有状态:

arr[id] = blankImage;

首先克隆现有数组,以免改变当前状态中的任何内容:

const newArr = [...images];
newArr[id] = blankImage;
return newArr;

images 是您的状态,您正在执行状态突变 (arr[id] = blankImage;) 而不是使用新数组更新状态。将现有状态映射到新的数组对象,并通过将 id 与索引匹配来更新图像。

const removeImage = (id) => {
  return images.map((image, index) => index === id ? blankImage : image);
};