【问题标题】:(react-window) How to pass props to {Row} in <FixedSizeList>{Row}</FixedSizeList>(react-window) 如何在 <FixedSizeList>{Row}</FixedSizeList> 中将 props 传递给 {Row}
【发布时间】:2019-07-13 09:37:47
【问题描述】:

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

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

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

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

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

这样做的正确方法是什么?

【问题讨论】:

  • 正确使用Row的方式是
  • 很遗憾,还是出现同样的错误
  • 显示更多代码...什么是行组件...还是一个函数?

标签: reactjs react-props react-window


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这也有效:

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

    像这样在行中使用:

    const Row = props => {
      console.log(props.yourCustomProp);
      return (
        <div>
          ...
        </div>
      );
    };
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        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)
        

        【讨论】:

          【解决方案5】:

          这是Function as Child Component 模式。查看更多:here

          其他选择:

          <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>
            );
          };
          

          【讨论】:

            【解决方案6】:
            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>
                )
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-03-19
              • 2021-07-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多