gpt4 book ai didi

javascript - React js 重新渲染表单中的大量组件

转载 作者:行者123 更新时间:2023-12-03 08:44:12 25 4
gpt4 key购买 nike

我有一个非常大的动态表单,它是根据通过 AJAX 收集的数据呈现的。

有一个包含表格的表单。该表包含一个标题,然后包含一系列行(由状态数据确定)。每行都有一系列单元格(也由状态数据确定)。每个单元格都包含一个复选框。

我的问题是在哪里维护大量复选框的状态。最初我的方法是让复选框控制组件,每个单元格保持其复选框的状态。

我还尝试将选择框的状态实现为父表单组件本身的状态。

前一种方法的问题是,当我提交表单时,我没有表单级别的状态,因为它被埋在单元格后代中。我能以某种方式得到这个状态吗? findDomNode 似乎只是当前组件,而不是级联组件。此外,标题单元格具有复选框,每当检查列中的所有行时都会检查这些复选框,此解决方案不允许我获得更新该信息的信息。

后一种方法的问题是,当我对一个复选框进行更改时,状态更改会导致表单组件重新渲染,进而导致整个表格重新渲染(或至少调用它的渲染方法)。这非常耗时,并且对于一个大表(通常可以是 100x50)来说,重新渲染需要非常不友好的时间。

归根结底,选中复选框的影响应该非常小。复选框本身应该更新,并且如果列的完全选择状态已更改,则可能需要更新列标题才能选中/取消选中。就是这样。

我已经删除了很多代码,但这基本上就是我正在处理的内容。了解表中的单元格复选框正在跟踪应将哪些标签应用于图像可能会有所帮助。表头单元格跟踪哪些标记(从图像名称中提取的文本)映射到哪些标签。当这种情况发生变化时,该列必须重新渲染(我还没有解决的另一个问题,我怀疑如果不完全重新渲染所有内容,这将再次变得困难)。

var AutoTagForm = React.createClass({
getInitialState: function() {
return {data: {
tags: [],
images: {},
tokens: [],
tokenTagMap: {}
}
};
},
componentDidMount: function() {
$.ajax({
url: this.props.url,
type: "POST",
data: { imageIds: this.props.images },
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},

onSubmit: function(e) {
e.preventDefault()

// Submit the updates to the server
},

cellCheckedChange: function(image, tag) {
// If the image has the tag, add it. Otherwise remove it

var tagIndex = image.checkedTags.indexOf(tag)

// TODO Perhaps it is safer to find the image object in this.state.data?
if (tagIndex === -1) {
image.checkedTags.push(tag);
} else {
image.checkedTags.splice(tagIndex, 1);
}

this.setState({
data: this.state.data
})

},

render: function() {
var images = this.state.data.images;
var tokenTagMap = this.state.data.tokenTagMap;
var cellCheckedChange = this.cellCheckedChange;

var rowNodes = Object.keys(images).map(function(key){
if (images.hasOwnProperty(key)) {
var image = images[key];

return (
<AutoTagImageRow key={image.id}
image={image}
tokenTagMap={tokenTagMap}
cellCheckedChange={cellCheckedChange} />
);
}
});

return (
<form ref="form" onSubmit={this.onSubmit} id="updateAllForm" className={'autotagForm'}>
<div>
<input type="submit"
value="Apply" />
</div>

<div>
<table>
<thead>
<AutoTagHeaderRow tags={this.state.data.tags}
tokens={this.state.data.tokens}
tokenTagMap={this.state.data.tokenTagMap} />
</thead>

<tbody>
{rowNodes}
</tbody>

</table>
</div>
</form>
);
}
});


var AutoTagImageRow = React.createClass({
render: function() {
var image = this.props.image;
var tokenTagMap = this.props.tokenTagMap;
var cellCheckedChange = this.props.cellCheckedChange;

var cellNodes = Object.keys(tokenTagMap).map(function(token){
if (tokenTagMap.hasOwnProperty(token)) {
return (
<AutoTagImageRowCell image={image}
token={token}
tokenTagMap={tokenTagMap}
cellCheckedChange={cellCheckedChange} />
);
}
});

return (
<tr>
{cellNodes}
<td>{image.clientPath}</td>
</tr>
);
}
});


var AutoTagImageRowCell = React.createClass({

isTagged: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];

return (image.tags.indexOf(tag) !== -1);
},

isChecked: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];

return (image.checkedTags.indexOf(tag) !== -1);
},

handleCheckedChange: function() {
var image = this.props.image;
var token = this.props.token;
var tokenTagMap = this.props.tokenTagMap;
var tag = tokenTagMap[token];

this.props.cellCheckedChange(image, tag);
},

render: function() {

var className = '';
if (this.isTagged()) {
className = 'success';
}

return (
<td className={className}>
<input type="checkbox"
checked={this.isChecked()}
onChange={this.handleCheckedChange} />
</td>
);
}
});

我是 React 新手,可能会做出一些糟糕的设计决策!这与我之前使用简单的 javascript 做事的方式非常不同,我热衷于遵循 React 哲学,但我觉得它几乎立即就出错了,因为这是我尝试做的第一件事过了教程。

最佳答案

好的。经过一些额外的研究,我发现了这个问题的一个很好的解决方案。

关键是能够判断哪些组件需要重新渲染。这是我之前考虑过的事情,但是确定图像行是否需要重新渲染所需的状态所需的比较几乎与重新渲染本身一样密集。

输入Immutable.js 。我将我的 javascript 对象转换为不可变的映射,并将我的数组转换为不可变的集合。像这样:

    for (var key in data.images) {
// data.images[key] = Immutable.fromJS(data.images[key]);

data.images[key] = Immutable.fromJS(
data.images[key], function (key, value) {
var isIndexed = Immutable.Iterable.isIndexed(value);
return isIndexed ? value.toSet() : value.toMap();
}
);
}

我还没有转换整个数据,因为其中还有其他数据位尚未更新为使用不可变,但这是可能的。

然后,当我从一个复选框处理 onChange 时,我会在表单级别实现它,如下所示:

  cellCheckedChange: function(imageId, tagId) {
var images = this.state.data.images;
var image = images[imageId];

// If the image has the tag, add it. Otherwise remove it
var checked = image.hasIn(['checkedTags', tagId]);

images[imageId] = image.update('checkedTags', function(value) {
return checked ? value.delete(tagId): value.add(tagId);
});

this.setState({
data: this.state.data
});

},

因此,对不可变对象(immutable对象)的更新会导致创建新对象。这将对不可变的状态结构产生向上的级联效应,因为对子级的任何更改都需要一个新的父级。不过,任何未直接更新或通过向上级联更新的状态仍然是相同的对象,这很重要,因为您可以独立地推理这些对象。

最后,我更新了图像行组件,仅在图像是新对象时更新(如果图像或任何后代已更新,则将是新对象):

var AutoTagImageRow = React.createClass({
render: function() {
...
},
// Only update an image row that has had a modified state
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.image !== this.props.image;
}
...
});

因此,当发生更新时,会发生更多的工作来操作 javascript 状态,但作为返回,我可以很容易地推断出哪些内容已更改,哪些内容未更改!

正如我上面提到的,不可变对象(immutable对象)的嵌套层次结构中未替换的任何部分都是相同的对象,因此可以将它们与旧结构的子级进行比较,以查看它们是否已使用结果进行更新但他们没有。这是一个独立的示例。

var Immutable = require('immutable');

var input = {
'1': 'aaa',
'2': [1,2,3,4]
};

var x = Immutable.fromJS(
input, function (key, value) {
var isIndexed = Immutable.Iterable.isIndexed(value);
return isIndexed ? value.toSet() : value.toMap();
}
);

// Get another reference to x
var y = x;

// Update the array stored in '2'
x = x.update('2', function(v) {
return v.add(7);
});

// object '1' remains the same JS object
console.log(x.get('1') === y.get('1')); //True

// object '2' is a new JS object
console.log(x.get('2') === y.get('2')); //False

// Overall 'x' is a new JS object
console.log(x === y); //False

关于javascript - React js 重新渲染表单中的大量组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32958634/

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