#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>
Для меня это не так «читаемо».