17

我正在使用名为react-window 的库

当我像这样将道具传递给它的行时:

{Row({...props, {otherProps}})}

它给了我一个类似的错误:

React.createElement: type is invalid -- 期望一个字符串(对于内置组件)或一个类/函数(对于复合组件)但是得到:...

正确的方法是如何做到这一点?

4

6 回答 6

28

您将道具添加到父元素的数据属性。注意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

于 2019-07-13T12:16:31.993 回答
2

这也有效:

  <List
    ...
  >
    {(props) => Row({...props, yourCustomProp})}
  </List>

像这样在行中使用:

const Row = props => {
  console.log(props.yourCustomProp);
  return (
    <div>
      ...
    </div>
  );
};
于 2021-05-06T19:05:16.447 回答
1

您可以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

于 2019-08-28T21:43:46.383 回答
1

我发现这非常令人困惑,但这是我的代码(希望它可以提供帮助):

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)
于 2019-10-17T13:44:49.250 回答
0
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>
    )
}
于 2022-03-06T03:16:14.680 回答
0

这是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>
  );
};
于 2022-02-01T14:23:04.233 回答