组件是否应该检查其道具?

时间:2019-03-29 11:14:40

标签: javascript reactjs

比方说,我们有一个父组件,该父组件呈现一个Notes组件,该组件呈现一些便笺,并且数据仅由notes组成,有时可以为null(=没有注释),有时还可以是字符串。数据本身来自我们无法控制的外部API。

选项A

// Parent
<Screen>
    {!!notes && (<Notes>{notes}</Notes>} // <--- RELEVANT LINE
</Screen>


// Notes.js
function Notes({notes}) {
  return (
    // Render the notes somehow 
  )
}

选项B

// Parent
<Screen>
  <Notes>{notes}</Notes>
</Screen>


// Notes.js
function Notes({notes}) {
  if(!notes) {  //                          <--- RELEVANT LINE
    return null;
  }

  return (
    // Render the notes somehow 
  )
}

基本上,将数据检查放在哪里更好?为什么?

2 个答案:

答案 0 :(得分:1)

我会说是的,您应该检查组件中使用的道具。让我们以您的notes为例。我不知道数据notes包含什么,但可以说它是Array[Objects]。您的数据可能看起来像这样(JSON)。

"notes": [
  {
    "day": "Monday",
    "time": "12:00pm",
    "note" "Some detail about your note for Monday"
  },
  {
    "day": "Tuesday",
    "time": "12:00pm",
    "note" "Some detail about your note for Tuesday"
  },
   {
    "day": "Wednesday",
    "time": "12:00pm",
    "note" "Some detail about your note for Wednesday"
  },
]

您的父组件可能看起来像这样:

class Parent extends component {
  displayNotes = () => {
    const { notes } = this.props;

    return (
      <StyledNoteWrapper>
        {notes.map(({
          day,
          time,
          note,
        }, index) => (
          <Note
            key={index + note}
            day={day}
            time={time}
          />
          ),
        )}
      </StyledNoteWrapper>
    );
  };

  render() {
    const { notes } = this.props;

    if (notes.length) return null;

    return (
      <div>
        {this.displayNotes()}
      </div>
    );
  }
}

如果没有if语句来检查notes的长度是否为0,则在布尔上下文中遇到该错误时将其视为false。 mozilla上的这篇帖子通过其他示例对此进行了描述。然后,您的组件将转到方法displayNotes,该方法将在undefined上运行map函数,这将导致您的组件崩溃,这显然很糟糕。因此,我认为,在合适的情况下,render()中像这样的简单检查非常简单。

我可以想到的另一个示例,您想对其进行简单检查的是上面示例的一个补充。在上述情况下,您有一个有效的日期和时间,但有一个空的注释。这可能在您的child组件中。

<StyledNoteWrapper>
  {day &&
    <StyledDay
      prop1={prop1}
      prop2={prop2}
    >
      {day}
    </StyledDay>
  }
  {time &&
    <StyledTime
      prop1={prop1}
      prop2={prop2}
    >
      {time}
    </StyledTime>
  }
  {note &&
    <StyledNote
      prop1={prop1}
      prop2={prop2}
    >
      {note}
    </StyledNote>
  }
</StyledNoteWrapper>

StyledNoteWrapperStyledTimeStyledNote中的每一个都是样式div。就像我上面说的,note是未定义的,您不希望呈现StyledNote,因为这将意味着不需要/不必要的DOM结构,这可能会导致性能问题(非常小,但规模很大)可能会有很大的不同,再加上为什么要渲染一个空的div?)。使用&&进行的此简单检查将意味着不渲染样式化时间的div容器。

所以回顾一下最后一个问题

  

将检查数据放在哪里更好?为什么?

更具体地说是option Aoption B。我认为这不是两者的简单选择。就像我上面提到的那样,我将首先在父级中执行检查(如第一个parent组件中所述),然后我还将在您的child组件中执行检查(如第二个{​​{1 }}组件。

同样,我不确定您的child道具中包含哪种数据,但希望以上示例可以为您指明正确的方向,就我个人而言,我总是会做最后检查我想要我的应用在生产过程中崩溃(或完全崩溃)。

答案 1 :(得分:0)

老实说,我认为没有“最好的方法”,但是可能有“在特定情况下最好的方法”。

例如,假设您还只希望显示以大写字母开头的注释:在这种情况下,您需要在Notes组件中进行检查,否则将仅填充{{ 1}}组件。
根据此示例,支票Screen是否像首字母的支票一样支票?按照这个想法,您可以将支票放入note !== null组件中。因此是选项B

此外,让我们谈谈React原理:创建组件来划分“工作”。在您的情况下,Notes要渲染一些笔记:您不在乎笔记是好/坏/短/长,其目的是渲染。
相反,Screen有责任“过滤”,“美化”,“设置样式”注释,因此,即使检查注释是否为null,也具有某种过滤功能。

总结,正如我所说,我认为没有最佳的解决方案,也没有正确的解决方案。但是,如果是我,我会遵循选项B ,这也是因为在我看来,这基本上是遵循React原则的路径。

编辑我也宁愿选择B,因为如果您美化了选项A的代码,则缩进可能会变成这样:

Notes

对我来说不是那么“可读”。