redux 推送新URL时多次调用React组件呈现

e7arh2l6  于 2022-11-24  发布在  React
关注(0)|答案(6)|浏览(126)

我正在构建一个PhotoViewer,当用户按下left或right时,它会改变照片。我使用React、Redux、react-router和react-router-redux。当用户按下left或right时,我会做两件事,一是使用this.context.replace()更新url,二是调度一个操作来更新当前查看的照片this.props.dispatch(setPhoto(photoId))。我订阅状态更改以进行调试。
上面的每一行都会触发一个新的状态变化。由于我更新了currentlyViewedPhoto,所以调度一个操作会更新存储;由于react-router-redux更新了存储中的url,所以更新url也会更新存储。当我调度操作时,在第一个重新呈现周期中,组件的render函数被调用了两次。在第二个重新呈现周期中,组件的render函数被调用一次。这正常吗?下面是相关代码:

class PhotoViewer extends Component {
  pressLeftOrRightKey(e) {
    ... code to detect that left or right arrow was pressed ...

    // Dispatching the action triggers a state update
    // render is called once after the following line
    this.props.dispatch(setPhoto(photoId)) // assume photoId is correct

    // Changing the url triggers a state update
    // render is called twice
    this.context.router.replace(url) // assume url is correct
    return
  }

  render() {
    return (
      <div>Test</div>
    )
  }
}

function select(state) {
  return state
}

export default connect(select)(PhotoViewer)

render被调用三次是正常的吗?这看起来有点小题大做,因为React将不得不做三次DOM比较。我想这并不重要,因为什么都没有改变。我是这个工具集的新手,所以请随时提出关于这个问题的任何问题。

zazmityj

zazmityj1#

如果在三个不同阶段设置状态,则组件也将重新呈现三次。
setState()将始终触发重新呈现,除非在shouldComponentUpdate()中实现了条件呈现逻辑。
(来源)
您可以在shouldComponentUpdate()中实作逻辑,以防止在遇到效能问题时发生不必要的重新转译。

ntjbwcob

ntjbwcob2#

我认为这是正常的。如果你没有明显的性能问题,我不会担心。如果性能开始成为一个问题,如果你确定某些状态改变不会改变呈现的组件,你可以考虑覆盖shouldComponentUpdate生命周期方法。
编辑:如果你只需要在你的shouldComponentUpdate生命周期方法中进行肤浅的比较,你也可以考虑扩展React.PureComponent而不是React.Component

6ljaweal

6ljaweal3#

这是一个老问题,我明白了,但我也注意到了这个问题。就像唐纳德的回答中所指出的那样,这似乎是正常的。我尝试了三种方法来解决我的具体情况:

  • 我关闭了React DevTools插件,看看它是否是重复消息的原因。
  • 我检查了一个不同的浏览器,看看是否是这个问题。
  • 我创建了一个简短的测试来检查它是否发生在简单的组件上。

前两种方法

禁用React DevTools插件不会更改记录到控制台中的消息数。
改变浏览器也没有效果,我试了Chromium和Firefox。
第三种方法
即使是最简单的组件似乎也会多次调用生命周期方法。
给定两个文件App.jscomponents/TestComponent.js,如下所示:
第一个
Test的生命周期方法被多次调用。

备注

  • 我用create-react-app来设置这个应用程序。
  • react版本为16.13.1。

结果和讨论

使用yarn start,我在控制台中得到以下内容:

App render
TestComponent.js:7 Test constructed
TestComponent.js:7 Test constructed
TestComponent.js:20 Test rendered
TestComponent.js:20 Test rendered
TestComponent.js:12 Test mounted

至少对我来说,yarn注意到开发版本没有优化,运行yarn build,然后用python -m http.server --directory build提供它,得到的页面没有重复的消息。
至于为什么你得到三个渲染而不是两个,我不能说。我的建议是尝试构建应用程序,看看问题是否在生产构建中仍然存在。
如果仍然遇到这个问题,也可以按照Donald的建议在shouldComponentUpdate中实现逻辑。

ecfdbz9o

ecfdbz9o4#

如果使用〉v16.3,则尝试删除**<React.StrictMode>**,它应该工作正常。
为什么?自从v16.3用于类组件和v16.8用于钩子以来,React引入了 <React.StrictMode> 以便使到Concurrent React的过渡(在不久的将来)更加 * 对开发人员友好 *,因为渲染阶段可以被多次调用。
以下文章值得一读:
React Components rendered Twice
React Components render twice and drive me crazy
Wait, you're not using <React.StrictMode>?!

注意:这仅适用于开发环境。

1sbrub3j

1sbrub3j5#

我<React.StrictMode>的案子也是这样

n3ipq98p

n3ipq98p6#

您可以在以下操作之前删除React.StrictMode

root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );

至:之前:

root.render(
        <App />
    );

index.js中的文件默认值

相关问题