- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有人请用一个简单的例子向我解释 React 文档的最后一段,它是关于 React.PureComponent 的,我见过的所有例子都是高级的,我刚刚开始了解这个概念,我看不出它到底是什么指。 正是 child 也应该“纯洁”的一点 .
据我所知,我认为这种说法言过其实,因为如果父亲不重新渲染自己,那么 children 也不会 ,或者,有什么东西让我无法想象,我无法想象它吗?这就是我需要一个简单示例的原因,我已经在这里查看了所有类似的问题,但它们是高级示例,并未涵盖我正在寻找的内容。
“此外,React.PureComponent 的 shouldComponentUpdate() 会跳过整个组件子树的 prop 更新。 确保所有子组件也是“纯” ”
最佳答案
我做了一些可以玩的东西。
我认为要实现的重要部分是只有一个区别,它是 shouldComponentUpdate
PureComponent
上的实现.
我也对 Make sure all the children components are also “pure”
感到困惑.据我了解,这意味着警告,作为指导方针,而不是绝对不要。当您将父级设置为 PureComponent 时,所有子级都会受到影响。但是有人不习惯shouldComponentUpdate
(PureComponent)在树中混合两者时可能会对 child 的行为(不更新)感到惊讶。
以第二个片段 this.state.quotes[0].text = "StackOverflow save the day";
为例.使用 Component
时两个<List/>
和 <ListElement/>
, 任意 setState
会更新 View 。但是当使用 PureComponent
仅在 <List/>
, 有人可能会期待 <ListElement/>
更新,但不会。
想象一下,而不是写 <List/>
作为纯,和<ListElement/>
作为不纯洁的,他们警告不要做的事情。你会把两者都写成纯的。你会不会考虑做一些类似 this.state.quotes[0].text = "StackOverflow save the day";
的事情? ?不,你会从 this.state.quotes[0] = {...}
开始.然后你会看看哪个组件处理上面的数据,quotes
数组,处理数组的组件,它是纯的吗?是的,然后写this.state = [{...}]
反而。您执行此“重新创建引用/深拷贝”,直到找到第一个非纯组件。如果您遵循他们的建议,在第一个非纯组件处,您知道不会有任何其他过时的引用阻止您的渲染。
如果使用深度比较,您将永远不会遇到这个问题。我正在使用钩子(Hook)组件,它们更加友好。我建议你跳过类组件并使用钩子(Hook)。在 Hook 中实现 shouldComponentUpdate
您使用 React.memo .自 您决定如何比较 Prop ,很明显,如果您比较 previousList === newList
(浅比较),您将错过列表中的任何更新/添加/删除。当然,您会进行深入比较(使用 deep-equal
lib 或(避免)JSON.stringify(previousList) === JSON.stringify(newList)
。请注意,React.Memo
更好还有另一个原因,它只处理 Prop 比较,而不是像 PureComponent 一样处理状态和 Prop 比较。
我认为您不需要每个 child 都使用浅比较,如果组件渲染速度足够快,请使用 shouldComponentUpdate
(或 React.memo
)可能会使情况变得更糟(记住这是一种性能优化)。
下面展示了我们可以通过浅 Prop 比较(第一个片段)和浅层状态比较(第二个片段)得到的问题:
import { Component, PureComponent } from 'react';
interface Quote {
author: string;
text: string;
}
export class Playground extends Component {
state = {
quotes: [
{
author: 'Ambroise',
text: 'I like React.'
}
]
}
onClickOK () {
this.setState({
quotes: [
{
author: 'Ariel',
text: 'Prefer VueJS.'
}
]
});
}
// https://reactjs.org/docs/react-api.html#reactpurecomponent
// React.PureComponent implements it with a shallow prop and state comparison
// "prop comparison"
onClickIssue() {
if (window['dontMix']) {
alert("Please don't mix on click issues. Reload page.")
return;
}
window['dontMix'] = true;
// This won't work if <List/> is a PureComponent
// Note that we ALSO CHANGED the props for <ListElement/> here, different object, differents strings,
// but <ListElement/> will NOT re-render, regardless of <ListElement/> being pure or not.
const quotesUpdated = this.state.quotes;
quotesUpdated.pop();
quotesUpdated.push({
author: 'Thomas',
text: 'Prefer Angular.'
});
// Shallow props comparison, <List/> will compare array references
// `quotesUpdated === this.state.quotes` and because it is true,
// it will not re-render, or any of the childrens.
//
// The quote object is different, so <ListElement/>
// would be expected to re-render.
this.setState({
quotes: quotesUpdated
});
}
onClickIssue2() {
if (window['dontMix']) {
alert("Please don't mix on click issues. Reload page.")
return;
}
window['dontMix'] = true;
// This won't work if <ListElement/> is a PureComponent since the object in first index stay the same.
// Since we recreate the array, <List/> will always re-render regardless of <List/> being pure.
this.state.quotes[0].author = "Thomas";
this.state.quotes[0].text = "Prefer Angular.";
this.setState({
quotes: [
this.state.quotes[0],
]
});
}
render() {
return (
<section>
<button onClick={this.onClickOK.bind(this)}>Get updated</button>
<button onClick={this.onClickIssue.bind(this)}>Problem</button>
<button onClick={this.onClickIssue2.bind(this)}>Problem2</button>
<List quotes={this.state.quotes}/>
</section>
);
}
}
// Change PureComponent to Component, no problem with shallow comparison anymore.
class List extends PureComponent<{ quotes: Quote[]; }>{
render() {
return (
<ul>
{
this.props.quotes.map(
(e, i) => <ListElement key={i} quote={e}/>
)
}
</ul>
);
}
}
class ListElement extends PureComponent<{quote: Quote}> {
render() {
return (
<li>
<h3>{this.props.quote.author}</h3>
<p>{this.props.quote.text}</p>
</li>
);
}
}
第二个片段,侧重于状态浅比较,以及
<ListElement/>
以
Component
开头这次不是
PureComponent
.
import { Component, PureComponent } from 'react';
interface Quote {
author: string;
text: string;
}
export class Playground2 extends Component {
state = {
quotes: [
{
author: 'Ambroise',
text: 'I like React.'
}
]
};
render() {
return (
<section>
<List quotes={this.state.quotes}/>
</section>
);
}
}
// Note: Careful not to confuse state.quotes and props.quote
class List extends PureComponent<{ quotes: Quote[]; }> {
state = {
quotes: this.props.quotes
};
// https://reactjs.org/docs/react-api.html#reactpurecomponent
// React.PureComponent implements it with a shallow prop and state comparison
// "state comparison"
fail() {
for (let i = 0; i < this.state.quotes.length; i++) {
this.state.quotes.pop();
}
this.setState({
quotes: this.state.quotes
});
}
success() {
// This will never work, because `previousState === newState` (both are this.state)
// this.state.quotes = [];
// this.setState(this.state);
this.setState({
quotes: []
});
}
// It work if you change this class to Component
changeChild() {
// if you clicked another button reload the page to get initial state.
if (this.state.quotes.length === 0) {
alert("You clicked another button. Please reload page to test this one.");
}
// previously "I like React."
this.state.quotes[0].text = "StackOverflow save the day";
// NOTICE: Choose only one setState bellow, comment the others.
// Won't work
// this.setState({
// quotes: this.state.quotes
// });
// This will never work, because `previousState === newState` (both are this.state)
// this.state.quotes = [this.state.quotes[0]];
// this.setState(this.state);
// Won't work
this.setState(this.state);
// This will work when <List/> is a PureComponent and <ListElement/> a Component,
// both this.state and this.state.quotes are different
// this.setState({
// quotes: [this.state.quotes[0]]
// });
}
render() {
return (
<div>
<button onClick={this.fail.bind(this)}>Empty the list (FAIL if PureComponent)</button>
<button onClick={this.success.bind(this)}>Empty the list (SUCCESS)</button>
<button onClick={this.changeChild.bind(this)}>Change child (FAIL if PureComponent)</button>
<ul>
{
this.state.quotes.map(
(e, i) => <ListElement key={i} quote={e}/>
)
}
</ul>
</div>
);
}
}
// ATTENTION: This one start as a Component this time, instead of a PureComponent
class ListElement extends Component<{quote: Quote}, {author: string}> {
state = {
author: this.props.quote.author,
};
// Yep this work.
takeOwnership() {
this.setState({
author: "Constantin"
})
}
render() {
return (
<li>
<button onClick={this.takeOwnership.bind(this)}>Take ownership !</button>
<h3>{this.state.author}</h3>
<p>{this.props.quote.text}</p>
</li>
);
}
}
TLDR;我也觉得它令人困惑,它看起来更像是和建议,我建议不要过多关注它,并使用钩子(Hook)组件,您可以在其中进行更细粒度的控制,通过 Prop /状态比较和浅/深比较。
关于javascript - React.PureComponent 和子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72409607/
问题是,当用户回复彼此的帖子时,我必须这样做: margin-left:40px; 对于 1 级深度 react margin-left:80px; 对于 2 层深等 但是我想让 react div
我试图弄清楚如何将 React Router 与 React VR 连接起来。 首先,我应该使用 react-router dom/native ?目前尚不清楚,因为 React VR 构建在 Rea
我是 React 或一般编码背景的新手。我不确定这些陈述之间有什么区别 import * as react from 'react' 和 import react from 'react' 提前致谢!
我正在使用最新的稳定版本的 react、react-native、react-test-renderer、react-dom。 然而,react-native 依赖于 react@16.0.0-alp
是否 react 原生 应用程序开发可以通过软件架构实现,例如 MVC、MVP、MVVM ? 谢谢你。 最佳答案 是的。 React Native 只是你提到的那些软件设计模式中的“V”。如果你考虑其
您好我正在尝试在我的导航器右按钮中绑定(bind)一个功能, 但它给出了错误。 这是我的代码: import React, { Component } from 'react'; import Ico
我使用react native创建了一个应用程序,我正在尝试生成apk。在http://facebook.github.io/react-native/docs/signed-apk-android.
1 [我尝试将分页的 z-index 更改为 0,但没有成功] 这是我的codesandbox的链接:请检查最后一个选择下拉列表,它位于分页后面。 https://codesandbox.io/s/j
我注意到 React 可以这样导入: import * as React from 'react'; ...或者像这样: import React from 'react'; 第一个导入 react
我是 react-native 的新手。我正在使用 React Native Paper 为所有屏幕提供主题。我也在使用 react 导航堆栈导航器和抽屉导航器。首先,对于导航,论文主题在导航组件中不
我有一个使用 Ignite CLI 创建的 React Native 应用程序.我正在尝试将 TabNavigator 与 React Navigation 结合使用,但我似乎无法弄清楚如何将数据从一
我正在尝试在我的 React 应用程序中进行快照测试。我已经在使用 react-testing-library 进行一般的单元测试。然而,对于快照测试,我在网上看到了不同的方法,要么使用 react-
我正在使用 react-native 构建跨平台 native 应用程序,并使用 react-navigation 在屏幕之间导航和使用 redux 管理导航状态。当我嵌套导航器时会出现问题。 例如,
由于分页和 React Native Navigation,我面临着一种复杂的问题。 单击具有类别列表的抽屉,它们都将转到屏幕 问题陈述: 当我随机点击类别时,一切正常。但是,在分页过程中遇到问题。假
这是我的抽屉导航: const DashboardStack = StackNavigator({ Dashboard: { screen: Dashboard
尝试构建 react-native android 应用程序但出现以下错误 info Running jetifier to migrate libraries to AndroidX. You ca
我目前正在一个应用程序中实现 React Router v.4,我也在其中使用 Webpack 进行捆绑。在我的 webpack 配置中,我将 React、ReactDOM 和 React-route
我正在使用 React.children 渲染一些带有 react router 的子路由(对于某个主路由下的所有子路由。 这对我来说一直很好,但是我之前正在解构传递给 children 的 Prop
当我运行 React 应用程序时,它显示 export 'React'(导入为 'React')在 'react' 中找不到。所有页面错误 see image here . 最佳答案 根据图像中的错误
当我使用这个例子在我的应用程序上实现 Image-slider 时,我遇到了这个错误。 import React,{Component} from 'react' import {View,T
我是一名优秀的程序员,十分优秀!