gpt4 book ai didi

javascript - React 随时重新渲染任何内容

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

我是 React 新手,我正在构建一个 Web 应用程序,用于显示视频和带有转录单词的框。

这些文字可以编辑,并且可以通过工具提示或对话框显示一些数据。

主要的 React 组件从 API 下载数据并组成由一些组件组成的页面:顶栏、侧栏、播放器和转录框。

下载后,我将 json 数据存储在状态中,并通过 props 将其传递到组件中。该组件处理 json 对象(单词)并创建许多无状态组件(单词),以及一些 Prop (例如,工具提示、key Prop 、 id、className...)然后我将它们全部放入一个数组中并返回到转录框。

我注意到,每次我编辑父元素的主要状态(而不是转录组件使用的数据)时,单词都会重新渲染(我在react中启用了highlighy更新 Chrome 开发工具的选项卡)。

这对于少量单词(例如 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}&nbsp;
</div>;
};

export default Word;

我制作了一个关于该问题的短视频。在此 gif 中,您可以看到每次我按下一个单词(调用 handleClick 方法)时,Info.js 状态都会发生无用的 prop 变化。没有触及任何文字数据,但 Chrome 向我显示浅蓝色边框, react 已重新渲染文字。

Example

最佳答案

根据我对你问题的理解,你不必要地渲染了很多组件?

对于这些无状态组件,您可以做的是控制它们的渲染时间。例如,当它们收到不同的 Prop 时进行渲染。 (使它们成为无状态的纯组件)。您可以使用 memo() 来实现这一点。例如:

import React, { memo } from "react";
import { isEqual } from "../definedByYou";

const YourComponent = props => {
return <div>{props.text}</div>;
};

// When text changes (isEqual returns false) => component will render
function arePropsEqual(prevProps, nextProps) {
return isEqual(prevProps.text, nextProps.text);
}

export default memo(YourComponent, arePropsEqual);

其中 isEqual 是您定义的函数,当比较的 props 相同时返回 true

编辑

Accordion 到你的Word组件尝试:

import React, { memo } 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}&nbsp;
</div>;
};

// if your data prop is an object you can't just use "==="
function arePropsEqual(prevProps, nextProps) {
return prevProps.id === nextProps.id && prevProps.data === nextProps.data;
}

export default memo(Word, arePropsEqual);

编辑2

在 TranscriptionBox 组件中使用 shouldComponentUpdate:

shouldComponentUpdate(nextProps, nextState) {
return true; // Here check differences in state and props :)
}

关于javascript - React 随时重新渲染任何内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57323517/

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