ファイル入力によって選択された写真を表示し、それらを状態に保存するNp02という名前のreactフックがあります。ユーザーがファイルを選択すると、それらはグリッドで表示されます。これは機能しますが、選択した画像を削除したい機能がありますが、そうではありません。関数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;
ここで既存の状態を変更しています:
arr[id] = blankImage;
代わりに、現在の状態にあるものを変更しないように、最初に既存のアレイのクローンを作成します。
const newArr = [...images];
newArr[id] = blankImage;
return newArr;
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加