#javascript #reactjs #typescript #callback #jsx
#javascript #reactjs #typescript #обратный вызов #jsx
Вопрос:
Интересно, есть ли способ повторить такое же использование обратного вызова js в JSX, например:
[1,2,3].map(console.log) // Here map iterator takes care of passing values to iteratee.
Есть ли аналогичный способ передачи подобного компонента, т.Е.. вместо этого:
<List data={data} renderItem={item => <Post {...item} />} />
что-то вроде этого:
<List data={data} renderItem={<Post/>} />
Комментарии:
1. Если вы видите, что props очень похожи на функции обратного вызова, вы передаете что-то и используете это в дочерних элементах. Допустим, вы передаете функцию от родителя к дочернему элементу, дочерний элемент вызовет эту функцию так же, как вы передаете функцию обратного вызова функции A, а A вызовет функцию обратного вызова позже.
Ответ №1:
Ах, хорошо, только что узнал, что вы можете использовать компоненты как простые функции js:
<List data={data} renderItem={Post} />
Ответ №2:
Вы можете, но, исходя из опыта, это приводит к боли и плохому дизайну позже, когда эти компоненты растут и требования меняются. Компонент списка становится более эзотерическим, и трудно найти, где что должно быть.
Например, если вы хотите сделать что-то столь же простое, как рендеринг спонсируемого Post
, код становится излишне сложным:
// Index.js
<List data={data} renderItem={Post} renderSponsoredItem={SponsoredPost} />
// List.js
function List({ data, renderItem, renderSponsoredItem }) {
<div className={styles.list}>
data.map(dataItem => {
if (dataItem.sponsored) {
return renderSponsoredItem(dataItem);
} else {
return renderItem(dataItem);
}
});
</div>
}
… и в некотором смысле это в конечном итоге выглядит совсем не так, как React, и не использует простоту использования и удобочитаемость, которые возможны с React.
Альтернатива может выглядеть примерно так:
// Index.js
<List>
{data.map(dataItem => {
if (dataItem.sponsored) {
return <SponsoredPost post={dataItem} />;
} else {
return <Post post={dataItem} />
}
})
</List>
// List.js
function List({ children }) {
<div className={styles.list}>
{children}
</div>
}
Я обнаружил, что первая форма подходит для нечитаемого кода и неработоспособных, нечитаемых компонентов в долгосрочной перспективе, а последняя намного проще для чтения / работы.
Комментарии:
1. Спасибо за подробный ответ, но имхо, если мы посмотрим с уровня родительского компонента (в данном случае List), ему не нужно знать подробности о том, какой тип сообщения он должен отображать. В принципе, вы можете использовать условную логику в Post, чтобы определить, будет ли текущий элемент данных SponsoredPost или каким-либо другим типом Post. Кроме того, List на самом деле является компонентом из akveo.github.io/react-native-ui-kitten/docs/components/list /…
2. Как я уже сказал, вы можете пойти в этом направлении, но это почти всегда приводит к более запутанному коду и плохому дизайну компонентов. Вы, очевидно, ограничены кодом библиотеки, но IMO дизайн компонентов в этой библиотеке довольно плохой.