【发布时间】:2019-08-07 22:45:28
【问题描述】:
我是 React 新手,我正在构建一个 Web 应用程序,它显示一个视频和一个带有转录词的框。
单词可以编辑,并且可以通过工具提示或对话框显示一些数据。
主要的 React 组件从 API 下载数据并组成由一些组件组成的页面:顶栏、侧边栏、播放器和转录框。
下载后,我将 json 数据存储在 state 中,并通过 props 将其传递给组件。
该组件处理 json 对象(单词)并创建很多 stateless components,单词,还有一些道具(例如,工具提示,key 道具,id,className ...)然后我把所有这些都在一个数组中并返回到转录框。
我注意到,每次我编辑父元素的主要状态(不是转录组件中使用的数据)时,单词都会重新渲染(我在 chrome 开发工具的 react 选项卡中启用了highlighy updates) .
这对于少量单词(例如 50-100 个元素)没有问题,但对于数千个项目,它会在用户操作和图形更新之间产生很大的延迟。
我可能错过了重点:我做错了什么?
您能告诉我如何处理大量 JSON 对象项以正确方式响应组件吗?
编辑:我切断了不感兴趣的代码,留下最少的代码来重现我的意思。
此示例中包含转录和其他组件的主要组件是 Info.js。我把API下载的数据放在一个单独的文件中,因为数据很长,你可以在那里找到:https://pastebin.com/nw1A391y
Info.js
import React, { Component } from 'react';
import TranscriptionBox from '../partials/TranscriptionBox.js';
class Info extends Component {
/**
* Set default props
* @type {Object}
*/
static defaultProps = {
name: 'Info'
}
/**
* Component constructor
* @param {Object} props [Component props]
*/
constructor (props) {
// Make property available in this module
super(props);
this.state = {
task: {
attachments: [],
automatic_created: true,
clips: [],
creation_user: "https://example.com/",
end_datetime: "2019-08-02T04:30:03.022",
id: 498,
metadata: [],
owner_user: null,
source: "https://example.com/",
source_repr: "Hello",
start_datetime: "2019-08-02T04:00:03",
status: "https://example.com/",
status_repr: "created",
url: "https://example.com/"
},
transcription: [] // NOTE: Put here the transcription form the file attached!
}
}
onWordClick = () => {
console.log("onWordClick");
this.setState({
hello: 'onWordClick'
})
}
onActionChange = () => {
console.log("action change");
this.setState({
hello: 'onActionChange'
})
}
onTaskProgressChange = () => {
console.log("onTaskProgressChange");
this.setState({
hello: 'onTaskProgressChange'
})
}
render() {
return (<div>
<TranscriptionBox
key="transcription_box_component"
ref="transcription_box_component"
task={this.state.task}
transcription={this.state.transcription}
taskLoaded={true}
action={null}
progress={null}
selected={null}
isSpecialPressed={false}
handleActionChange={this.onActionChange}
handleWordClick={this.onWordClick}
handleProgressChange={this.onTaskProgressChange}
/>
</div>);
}
}
export default Info;
这是转录框组件,用于渲染 API 数据并在滚动框内生成文字对象。
TranscriptionBox.js
import React from 'react';
// Import classes and components
import Word from './Word.js';
// Import style
import '../styles/TranscriptionBox.css'
class TranscriptionBox extends React.Component {
/**
* Set default props
* @type {Object}
*/
static defaultProps = {
name: 'TranscriptionBox',
tempData: undefined
}
/**
* Component constructor
* @param {Object} props [Component props]
*/
constructor (props) {
// Make property available in this module
super(props);
// Set default state
this.state = {
visible: true,
value: '',
transcription: this.props.transcription,
lastPostion: 0,
inDownloading: false,
downloaded: false
}
}
/*
|-------------------------------------------------------------------------|
| ACTION HANDLE |
|-------------------------------------------------------------------------|
*/
/**
* Handle click action on transcription box word
* @param Event ev Double click event
* @return void
*/
handleWordClick = (ev) => {
// Get current action
let action = this.props.action;
// Get the target of click
let target = ev.currentTarget;
// Init word object
let data = false;
// Manage wordclick
this.props.handleActionChange(undefined);
}
/*
|-------------------------------------------------------------------------|
| ELEMENTS GENERATION |
|-------------------------------------------------------------------------|
*/
/**
* Call the ReactJS dangerouslySetInnerHTML to transform string into HTML
* @return {HTML} Html code
*/
renderTranscription = () => {
console.log("*** TB@renderTranscription");
// Create HTML tag from text transcription
return this._elaborateTranscription(this.props.transcription);
}
/**
* Elaborate transcription and create all tags
* // COMBAK: make clips tag manage array of clips
* @param array transcription The transcription to elaborate
* @return array The transcription elaborated
*/
_elaborateTranscription = (transcription) => {
// Init vars
let reactWord, word, wordObject, seconds;
// Init array
let elaborated = [];
// If transcription is null or empty transcription
if (!transcription || transcription.length < 1) {
// Init reactWord to be pushed
reactWord = <em key="no-transcription">Loading...</em>;
// Return a placeholder
elaborated.push(reactWord);
// Return elaborated
return elaborated;
}
// Get this context to me var
let me = this;
// Iterate each word and take the iterator count
transcription.forEach(function (transcriptionWord, i) {
// Create a copy
wordObject = {...transcriptionWord};
// If has no id
if (!transcriptionWord['id']) {
// Compose an unique id
wordObject['id'] = "word-" + i;
}
// Get seconds
seconds = parseInt(transcriptionWord['time']);
// Calculate the seconds at
wordObject['seconds'] = seconds;
// Create a new word react element
word = <Word key={wordObject.id}
handleDoubleClick={me.handleWordDoubleClick}
handleClick={me.handleWordClick}
{...wordObject} />;
// Push created tag into array
elaborated.push(word);
});
// Return elaborated text
return elaborated;
}
/*
|-------------------------------------------------------------------------|
| RENDER |
|-------------------------------------------------------------------------|
*/
/**
* Render component
* @return {} []
*/
render() {
return (
<div
id="transcription-box"
ref="transcription-box"
className='task-transcription-box-container border-secondary'>
{this.renderTranscription()}
</div>
);
}
}
// Export default component to be accessible in other components
export default TranscriptionBox;
这是无状态组件这个词。
Word.js
import React from 'react';
import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
const Word = props => {
return <div
key={props.id}
className='transcription-word'
data-id={props.id}
data-metadata=''
data-clips=''
data-seconds=''
data-datetime=''
onDoubleClick={props.handleDoubleClick}
onClick={props.handleClick}
>
{props.data}
</div>;
};
export default Word;
我为这个问题制作了一个简短的视频。在这个 gif 中你可以看到每次我按下一个词(方法 handleClick 被调用)和一个无用的 Info.js 状态变化的道具。没有触及任何文字数据,但 chrome 显示带有浅蓝色边框的 react 已经重新渲染了文字。
【问题讨论】:
-
好的,将编写一部分代码来重现它们。
-
@codekaizer,我用代码和更多问题解释更新了我的问题。谢谢
标签: javascript reactjs render