我有一个名为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;
答案 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);
};