현재 이미지를 목록에 추가 한 다음 나중에 업로드하기 위해 Meteor에 사용자 지정 React 구성 요소를 만들고 있습니다. 그러나 목록에서 이미지를 삭제하려고 할 때 항상 마지막 요소가 GUI에서 제거됩니다. 처음에는 이것이 잘못된 색인을 삭제에 사용하는 단순한 경우라고 생각했지만 그 이상의 것으로 밝혀졌습니다.렌더링 된 HTML이 React 구성 요소와 동기화되지 않았습니다.
이처럼 내 ImageList
구성 요소가 현재 모습입니다 :
import React from 'react';
import Dropzone from 'react-dropzone';
import cloneDeep from 'lodash.clonedeep';
import { ImageItem } from './image-item.js';
export class ImagesList extends React.Component {
constructor(props) {
super(props);
this.values = this.props.images || [];
this.onDrop = this.onDrop.bind(this);
this.addImages = this.addImages.bind(this);
this.deleteImage = this.deleteImage.bind(this);
this.imageChanged = this.imageChanged.bind(this);
}
onDrop(files) {
this.addImages(files);
}
onDropRejected() {
alert('Invalid file type');
}
addImages(files) {
files.forEach(file => {
this.values.push({
title: '',
description: '',
url: file.preview,
file,
});
});
this.forceUpdate();
}
deleteImage(index) {
console.log('index to delete', index);
console.log('images pre-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.values.splice(index, 1);
console.log('images post-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.forceUpdate();
}
imageChanged(index, image) {
this.values[index] = image;
this.forceUpdate();
}
render() {
console.log('--------RENDER--------');
return (
<div className="image-list">
<div className="list-group">
{this.values.length === 0 ?
<div className="list-group-item">
No images
</div>
:
this.values.map((image, index) => {
console.log('rendering image', image);
return (
<ImageItem
key={index}
image={image}
onDelete={() => { this.deleteImage(index); }}
onChange={(item) => { this.imageChanged(index, item); }}
deletable={true}
/>
);
})
}
</div>
<Dropzone
multiple={true}
onDrop={this.onDrop}
onDropRejected={this.onDropRejected}
className="dropzone"
activeClassName="dropzone-accept"
rejectStyle={this.rejectStyle}
accept={'image/*'}
>
<span>Drop files here</span>
</Dropzone>
</div>
);
}
}
ImagesList
구성 요소가 렌더링시 사용 (디버깅을 위해) 어떤 값으로 초기화 할 수 있습니다. 예를 들어
<ImagesList images={[
{ title: 'Image 1', description: 'Image 1 description', url: 'http://cssdeck.com/uploads/media/items/3/3yiC6Yq.jpg' },
{ title: 'Image 2', description: 'Image 2 description', url: 'http://cssdeck.com/uploads/media/items/4/40Ly3VB.jpg' },
{ title: 'Image 3', description: 'Image 3 description', url: 'http://cssdeck.com/uploads/media/items/0/00kih8g.jpg' },
]}/>
ImagesList
각 이미지에 대한 ImageItem
요소를 렌더링한다. 이것은이 구성 요소는 모습입니다 같은 :
import React from 'react';
import { RIEInput, RIETextArea } from 'riek';
export class ImageItem extends React.Component {
constructor(props) {
super(props);
this.placeholder = {
title: 'Title',
description: 'Description',
};
this.value = this.props.image;
}
render() {
return (
<div className="list-group-item">
<div className="text-content">
<h4>
<RIEInput
className="description"
value={this.value.title.length <= 0 ?
this.placeholder.title : this.value.title}
change={(item) => {
this.value.title = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
/>
</h4>
<span>
<RIETextArea
className="description"
value={this.value.description.length <= 0 ?
this.placeholder.description : this.value.description}
change={(item) => {
this.value.description = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
rows="2"
/>
</span>
</div>
<img className="thumb img-responsive"
style={{width: '20%' }}
src={this.value.url}
alt="Image"
data-action="zoom"
/>
{this.props.deletable ?
<div className="delete-btn">
<span onClick={this.props.onDelete}>
×
</span>
</div>
:
undefined }
</div>
);
}
}
의 내가 세 가지 이미지, 이미지 A, B 및 C가, 내가, 이미지 C이 사라집니다 삭제 버튼을 누른 후 이미지 B를 삭제하고 싶은 말은하자 GUI 대신.
deleteImage()
함수 내에서 ImagesList
의 인덱스를 로깅하고 삭제 전후에 값을 기록합니다. 로그 된 인덱스는 올 Y 른 것으로,이 경우 인덱스는 1
입니다. 삭제하기 전에 값은 이미지 A, B 및 C입니다. 삭제 후 값은 이미지 A 및 C입니다.
ImagesList
의 render()
기능 내에서 일부 로깅을 결정했습니다. 불행히도 이것은 또한 정확한 값 A와 C를 기록하지만, A와 B이 실제로 렌더링됩니다.
또한 로컬 변수에 forceUpdate()
과 함께 저장하는 대신이 구성 요소에 React 상태를 사용하려고했습니다.
내가 시도한 또 다른 사항은 Chrome 용 React Developer Tools 플러그인을 사용하는 것입니다. Devtools도 올바른 값을 표시하지만 GUI는 여전히 this screenshot과 같이 표시되지 않습니다.
나는 무엇을 시도 할 지에 대한 아이디어가 없으므로 도움을 받으실 수 있습니다! 제공된 스 니펫을 사용하면 Meteor 프로젝트를 생성하고이 버그를 재현 할 수 있습니다.
일반적으로 이미지 원본의 이미지를 변경해야합니다. 그들이 소품으로 당신에게 주어 졌기 때문에, 그 변화는 구성 요소 자체에서 일어나서는 안됩니다. 이는 대개 액션을 트리거 한 다음 전역 상태 관리자를 사용하여'props '에 매핑 된 상태를 업데이트함으로써 수행됩니다. 귀하의 질문에 시연하는 방식으로 구성 요소 업데이트를 어디에서 보았는지 궁금합니다. – MasterAM