gpt4 book ai didi

javascript - 渲染的 HTML 与 React 组件不同步

转载 作者:行者123 更新时间:2023-12-02 14:01:01 24 4
gpt4 key购买 nike

我目前正在 Meteor 中创建一个自定义 React 组件,用于将图像添加到列表中(然后上传它们)。然而,当我尝试从列表中删除图像时,最后一个元素总是从 GUI 中删除。最初我以为这只是一个简单的使用错误索引进行删除的案例,但事实证明并非如此。

这就是我的 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}>
&times;
</span>
</div>
:
undefined }
</div>
);
}
}

假设我有三个图像,图像 A、B 和 C,并且我想删除图像 B。按删除按钮后,图像 C 将从 GUI 中消失。

ImagesListdeleteImage()函数中,我正在记录要删除的索引,并记录删除之前和之后的值。记录的索引是正确的,在本例中为索引 1。删除前,值为图像 A、B 和 C。删除后,值为图像 A 和 C,因为它们应该是这样。

我决定也在 ImagesListrender() 函数中进行一些日志记录。不幸的是,这也记录了正确的值 A 和 C,但实际上渲染了 A 和 B

我还尝试对此组件使用 React 状态,而不是将其与 forceUpdate() 一起存储在本地变量中。

我尝试过的另一件事是使用 Chrome 的 React Developer Tools 插件。 Devtools 也显示正确的值,但 GUI 仍然不显示,如 this screenshot 中所示。 .

我目前不知道该尝试什么,任何帮助将不胜感激!使用我提供的代码片段,您应该能够创建 Meteor 项目并重现此错误。

最佳答案

根据 MasterAM 的建议,我设法找到了两种不同的解决方案。

<小时/>

A.) 使用componentWillUpdate()

this.value 变量仅设置一次,即在 ImageItem 组件的构造函数中设置。为了确保正确委派更改,您必须更新 componentWillUpdate() 函数内的 this.value。像这样的东西:

componentWillUpdate(nextProps, nextState) {
this.value = nextProps.image;
}
<小时/>

B.) 直接使用该属性

这绝对是更合适的解决方案。在这里,我们删除了 ImageItem 组件构造函数中的局部变量 this.value

render() 函数中,将 this.value 替换为 this.props.image。现在无需使用componentWillUpdate()函数,一切都按预期工作。

关于javascript - 渲染的 HTML 与 React 组件不同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40422125/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com