Должны ли компоненты проверять свои реквизиты?

#javascript #reactjs

#javascript #reactjs

Вопрос:

Допустим, у нас есть родительский компонент, который отображает компонент Notes, который отображает некоторые заметки, и данные состоят только из notes того, что иногда может быть null (= нет заметок), а иногда из строки. Сами данные поступают из внешнего API, который мы не контролируем.

Вариант A

 // Parent
<Screen>
    {!!notes amp;amp; (<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 
  )
}
  

В принципе, куда лучше поместить проверки для данных и почему?

Комментарии:

1. Рассматривали ли вы prop-types? npmjs.com/package/prop-types Это также зависит от того, являются ли данные, которые вы проверяете, специфичными для рендеринга этих компонентов. я бы сохранил это внутри конкретного компонента, чтобы не раздувать родительский. С другой стороны, необязательный рендеринг меньшего компонента только для возврата null может быть пустой тратой времени. тем не менее, я бы все равно использовал компонент, проверяющий его собственные реквизиты в 90% случаев.

2. Пока оба компонента являются вашими собственными и не должны использоваться кем-либо еще, это не имеет значения.

3. Сначала у вас должна быть модель на стороне API, и вы должны каким-то образом знать тип notes . Вы должны иметь Proptypes доступ к родительскому компоненту, чтобы проверить тип notes реквизита, а затем выполнить некоторую проверку на основе этого.

4. PropTypes не выполняются в рабочей среде, поэтому они не имеют отношения к данному случаю.

5. Также, @NicolaeMaties, в исходном сообщении я определил тип либо как null, либо как string.

Ответ №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, что считается ложным при обнаружении в логическом контексте. Этот пост в Mozilla описывает это с другими примерами. Затем ваш компонент перейдет к методу, displayNotes который будет запускать функцию map для undefined, что приведет к сбою вашего компонента, что, очевидно, плохо. Итак, на мой взгляд, при необходимости простая проверка, подобная этой в render() , великолепна и проста.

Другой пример, который я могу придумать, для которого вы хотите выполнить простую проверку, — это продолжение примера выше. В приведенном выше сценарии у вас есть действительный день и время, но пустое примечание. Это может быть в вашем child компоненте.

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

Каждый, StyledNoteWrapper , StyledTime и StyledNote является стилизованным div . Как я сказал выше, note не определено, вы бы не хотели, чтобы ваша StyledNote отображалась, поскольку это означало бы нежелательную / ненужную структуру DOM, которая может вызвать проблемы с производительностью (очень маленькая, но в больших масштабах может иметь большое значение, плюс зачем вам отображать пустой div?). Эта простая проверка с помощью amp;amp; будет означать, что контейнер div в указанное время не отображается.

Итак, резюмируя ваш последний вопрос

куда лучше поместить проверки для данных и почему?

Более конкретно option A или option B . Я не думаю, что это простой выбор из двух. Как я упоминал выше, я бы сначала выполнил проверку в parent (как описано в моем первом parent компоненте) И тогда я бы также выполнил проверки в вашем child компоненте (как описано в моем втором child компоненте).

Опять же, я не уверен, какие данные у вас есть в вашем notes реквизите, но, надеюсь, приведенные выше примеры могут указать вам правильное направление, лично я всегда выполняю проверки там, где могу, поскольку последнее, чего я хочу, это чтобы мое приложение зависало во время производства (или вообще).

Ответ №2:

Честно говоря, я не думаю, что есть «лучший способ», но может быть «лучший способ в конкретном сценарии».

Например, предположим, что вы также хотите отображать только заметки, начинающиеся с заглавной буквы: в этом случае у вас была бы проверка в Notes компоненте, в противном случае вы бы просто заполнили Screen компонент.
Исходя из этого примера, не является ли проверка note !== null проверкой, подобной проверке первой буквы? Следуя этой идее, вы бы поместили проверку внутри Notes компонента. таким образом, вариант B.

Кроме того, давайте поговорим о принципе React: Компоненты создаются для разделения «заданий». В вашем случае Screen хочет отобразить некоторые заметки: вам все равно, хорошие ли заметки / плохие / короткие / длинные, его цель — отобразить.
Вместо этого Notes обязан «фильтровать», «украшать», «стилизовывать» заметки, таким образом, даже проверка того, являются ли заметки нулевыми, является своего рода функцией фильтрации.

Подводя итог, как я уже сказал, я не думаю, что есть лучшее решение, ни правильное решение. Но, если бы это был я, я бы выбрал вариант B, также потому, что мне кажется, что это путь, который в основном соответствует принципам React.

РЕДАКТИРОВАТЬ Я также предпочитаю вариант B, потому что, если вы украсите код варианта A, может случиться так, что его отступ станет чем-то вроде:

 <Screen>
  {!!notes amp;amp; (
    <Notes>
      {notes}
    </Notes>
  } 
</Screen>
  

Для меня это не так «читаемо».