反应钩子不点击更新

时间:2020-09-27 23:40:28

标签: javascript reactjs react-hooks react-state-management

我有一个名为Np02的反应钩子,该钩子显示通过文件输入选择的照片并将其保存到状态。当用户选择文件时,这些文件将以网格形式显示给他。这行得通,但是有些功能我想删除所选的图像,而事实并非如此。函数removeImage运行,输出我期望的数组,但是状态不会改变。我已经尝试将setImages移到removeImages函数或其他位置,但是状态本身不会改变,并且当我在图像上添加useEffect时,它仅在选择图像时才更改,而在我要移除它们时不改变。 为什么状态没有更改?

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;

2 个答案:

答案 0 :(得分:2)

您要在此处更改现有状态:

arr[id] = blankImage;

请先克隆现有的数组,以免突变当前处于状态的任何东西:

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

答案 1 :(得分:2)

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

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