组件仅在包装在 `div` 中时才会更新

Posted

技术标签:

【中文标题】组件仅在包装在 `div` 中时才会更新【英文标题】:Component only gets updated when wrapped in a `div` 【发布时间】:2020-07-01 19:21:35 【问题描述】:

我遇到了一个问题,即我的组件仅在包装在 div 中时才会更新。

我有一个switch statement 来渲染不同版本的孩子。当我将第二个案例包装在div 中时,似乎一切正常,但如果这个div 不存在,它就不会按预期工作。 _getCurrentInputStateselectedBlock 似乎没有按应有的方式更新。

const Parent= () => 

    /* ... */

    const _renderEditorPanel = () =>
        const currentBlockType = blockList[selectedBlock].type
        switch(currentBlockType)
          case 'description': return (
            <EditorPanel 
              currentBlockType='description'
              selectedBlock=selectedBlock
              _getBlock=_getBlock
              _getCurrentInputState=_getCurrentInputState
              _setCurrentInputState=_setCurrentInputState
            />
          )
          case 'skills_and_requirements': return (
            <div>  /* <<<<<<<<<<<<<<<<<<<<<<<< This is needed to really update the child?
            */
            <EditorPanel 
              currentBlockType='skills_and_requirements'
              selectedBlock=selectedBlock
              _getBlock=_getBlock
              _getCurrentInputState=_getCurrentInputState
              _setCurrentInputState=_setCurrentInputState
            />
            </div> /* <<<< and this.*/
          );
          default: return (
            <EditorPanel 
              currentBlockType='default'
              selectedBlock=selectedBlock
              _getBlock=_getBlock
              _getCurrentInputState=_getCurrentInputState
              _setCurrentInputState=_setCurrentInputState
            />
          );
      
      


      return (    
        <StyledJobEditor>
          _renderEditorPanel()    
          <div className="preview_panel">
            <div>
            <button onClick=
              () => setSelectedBlock("1")
            >1</button>
            <button onClick=() => setSelectedBlock("2")>2</button>
            <button onClick=() => setSelectedBlock("0")>0</button>
            </div>

              /*
                The sidebar will be an arraw of block. We should expect to use the .map function here.
              */

          </div>
        </StyledJobEditor>
      );
    

【问题讨论】:

【参考方案1】:

首先,您根本不需要开关盒。其次,您正在返回 html,因此它是一个组件而不是一个方法,因此以大写开头的方法名称。您可以将代码简化为

const RenderEditorPanel = () => 
        const currentBlockType = blockList[selectedBlock].type || 'default';
        return (
        <EditorPanel 
              currentBlockType=currentBlockType
              selectedBlock=selectedBlock
              _getBlock=_getBlock
              _getCurrentInputState=_getCurrentInputState
              _setCurrentInputState=_setCurrentInputState
            />
        )
      

另外,当我们使用这个组件时,它应该如下所示

<RenderEditorPanel />

【讨论】:

嗨 Nayan,谢谢您的回复。实际上我正在返回 JSX 并且需要 switch 语句,因为随着时间的推移我会堆叠多个案例,而且我更喜欢使用 switch 语句,这样我的代码就会保持干净。【参考方案2】:

我相信您看到这个的原因是 react 无法告诉它应该挂载同一组件的新实例。通过将一个更改为包裹在 div 中,反应看到它的不同并重新安装所有内容。否则,它只是将其视为道具更改。

没有看到EditorPanel 的实现,我无法提供更多见解,但我猜你未更改的道具只在安装或类似的东西上设置一次。

就像映射元素时一样,您可以为开关中的每个元素提供key,以告知 react 每个元素都是唯一的。

switch (currentBlockType) 
  case 'description': return (
    <EditorPanel
      key="description"                 // Add this
      currentBlockType='description'
      selectedBlock=selectedBlock
      _getBlock=_getBlock
      _getCurrentInputState=_getCurrentInputState
      _setCurrentInputState=_setCurrentInputState
    />
  )
  case 'skills_and_requirements': return (
    <EditorPanel
      key="skills_and_requirements"      // Add this
      currentBlockType='skills_and_requirements'
      selectedBlock=selectedBlock
      _getBlock=_getBlock
      _getCurrentInputState=_getCurrentInputState
      _setCurrentInputState=_setCurrentInputState
    />
  )
  default: return (
    <EditorPanel
      key="default"                      // Add this
      currentBlockType='default'
      selectedBlock=selectedBlock
      _getBlock=_getBlock
      _getCurrentInputState=_getCurrentInputState
      _setCurrentInputState=_setCurrentInputState
    />
  )

【讨论】:

这成功了!我知道这与仅部分渲染我的元素有关,但我可以弄清楚如何强制重新安装所有内容。感谢您的帮助! 是的,基本上反应就是看到 - 上次我渲染了一个 EditorPanel 组件,这次我也应该渲染一个,我会假设它们是同一个并且重用第一个实例。通过传递一个键,您可以更好地控制 react 如何解释渲染相同的组件。当您添加 div 时,它们不再匹配,因此 react 不会三思而后行并安装一个新实例。

以上是关于组件仅在包装在 `div` 中时才会更新的主要内容,如果未能解决你的问题,请参考以下文章

仅在窗口调整大小时防止 div 重叠(带样式组件)

有没有办法单击 div 容器包装的 react-router 链接组件?

有没有办法单击 div 容器包装的 react-router 链接组件?

React 组件中是不是有任何必需的 div 包装器

React 子组件仅在刷新时更新

仅在第一个组件通过验证时有条件地更新第二个组件