(ответное окно) Как передать реквизит {Row} в <FixedSizeList>{Row}</ FixedSizeList>
Я использую библиотеку под названием реагирующее окно
Когда я передаю реквизит в свой ряд, как это:
{Row({...props, {otherProps}})}
это дало мне ошибку что-то вроде:
React.createElement: тип недействителен - ожидал строку (для встроенных компонентов) или класс / функцию (для составных компонентов), но получил:...
Как правильно сделать это?
6 ответов
Вы добавляете реквизиты в свойство data родительского элемента. Обрати внимание на itemData={{ testData: "123", otherData: true }}
,
const Example = () => (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
itemData={{ testData: "123", otherData: true }}
>
{Row}
</List>
)}
</AutoSizer>
);
И тогда в компоненте Row вы можете получить данные из реквизита, как это const { data, index, style } = props;
const Row = props => {
const { data, index, style } = props;
return (
<div>
{index} Row {data.testData}
</div>
);
};
Демонстрация, чтобы увидеть это в действии: https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-dtnre
Это тоже работает:
<List
...
>
{(props) => Row({...props, yourCustomProp})}
</List>
Используйте в строке так:
const Row = props => {
console.log(props.yourCustomProp);
return (
<div>
...
</div>
);
};
import { CSSProperties, memo, useCallback, useMemo } from 'react'
import AutoSizer from 'react-virtualized-auto-sizer'
import { areEqual, FixedSizeList } from 'react-window'
interface Data {
someProp: string
users: Array<{ id: number }>
someMethod(id: number): string
}
interface RowProps {
data?: Data
index?: number
style?: CSSProperties
}
const Row = memo((props: RowProps) => {
const { data, index, style } = props
const { someProp, users, someMethod } = data || {}
const { id } = users[index] || {}
return (
<div style={style}>
{someProp}: {someMethod(id)}
</div>
)
}, areEqual)
interface ComponentProps {
someProp: string
users: Array<{ id: number }>
}
const SomeComponent = (props: ComponentProps) => {
const { someProp, users } = props
const someMethod = useCallback(
(id: number) => {
return `${someProp.slice(-4)}-${id}`
},
[someProp],
)
const itemData = useMemo(
() => ({
someProp,
users,
someMethod,
}),
[someProp, users, someMethod],
)
return (
<AutoSizer disableWidth>
{({ height }) => (
<FixedSizeList
itemCount={users.length}
itemData={itemData}
itemSize={48}
height={height}
width={'100%'}
>
{Row}
</FixedSizeList>
)}
</AutoSizer>
)
}
Я нашел это очень запутанным, но вот мой код (надеюсь, что это может помочь):
class Row extends PureComponent {
render() {
const { data, index, style } = this.props
const {
classes,
itemsPerRow,
shows,
setCardMarkerHover,
resetCardMarkerHover,
playTrack,
} = data
const items = []
const fromIndex = index * itemsPerRow
const toIndex = Math.min(fromIndex + itemsPerRow, shows.length)
//console.log(this.props)
for (let i = fromIndex; i < toIndex; i++) {
items.push(
<ShowCard
key={i}
item={shows[i]}
setCardMarkerHover={setCardMarkerHover}
resetCardMarkerHover={resetCardMarkerHover}
playTrack={playTrack}
/>
)
}
// console.log(items)
return (
<div className={classes.Row} style={style}>
{items}
</div>
)
}
}
class FastList extends React.Component {
getItemData = memoize(
(
classes,
itemsPerRow,
shows,
setCardMarkerHover,
resetCardMarkerHover,
playTrack
) => ({
classes,
itemsPerRow,
shows,
setCardMarkerHover,
resetCardMarkerHover,
playTrack,
})
)
render() {
const {
shows,
classes,
setCardMarkerHover,
resetCardMarkerHover,
playTrack,
} = this.props
//console.log(this.props)
// console.log(shows);
return (
<div style={{ height: "90vh", minWidth: "20vw" }}>
<AutoSizer>
{({ height, width }) => {
const itemsPerRow = 1
const rowCount = Math.ceil(shows.length / itemsPerRow)
const itemData = this.getItemData(
classes,
itemsPerRow,
shows,
setCardMarkerHover,
resetCardMarkerHover,
playTrack
)
return (
<div>
<List
height={height}
itemCount={rowCount}
itemData={itemData}
itemSize={CARD_SIZE}
width={width}
>
{Row}
</List>
</div>
)
}}
</AutoSizer>
</div>
)
}
}
FastList.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(FastList)
Вы можете иметь Row
вернуть функцию. Вы можете получить доступ к обоим параметрам из определения функции. Итак, вы можете передать данные непосредственно в Row()
вызов.
const Example = () => (
<AutoSizer>
{({ height, width }) => (
<List
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row({ testData: "123", otherData: true })}
</List>
)}
</AutoSizer>
);
И Row
функция:
const Row = data => props => {
const { index, style } = props;
return (
<div>
{index} Row {data.testData}
</div>
);
};
Вот демоверсия: https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-tqdpf
Это
Function as Child Component
Шаблон. Подробнее: здесь
Другая альтернатива:
<List
itemData={{
...yourProps
}}>
...
>
{(props) => <Row {...props}/>}
</List>
Строка
const Row = ({ data, index, style }) => {
const { ...yourProps } = data
return (
<div style={style}> // Don't forget to pass the style
...
</div>
);
};