javascript - 重用React 'key'

标签 javascript reactjs

我想知道在组件之间重用 react 键是否正常。在 Row 组件中,我从列组件中获取了 key 并重用它来映射 Row 子级

const Table = props => {
  const { data, children, showHeader } = props;
  return (
    <div className="table">
      {showHeader && <TableHead children={children} />}
      {data.map(data => {
        return <Row key={data.id} data={data} children={children} />;
      })}
    </div>
  );
};

const TableHead = props => {
  const { children } = props;

  return (
    <div className="table-row">
      {children.map(col => {
        const { title, field, width } = col.props;
        return (
          <div className="table-col" key={field}>
            <div
              className="table-cell table-cell-head"
              style={{
                width: width
              }}
            >
              {title}
            </div>
          </div>
        );
      })}
    </div>
  );
};

//HERE I GET key from Column component and reuse it for rows (number of columns === number of rows)
const Row = props => {
  const { data, children } = props;
  return (
    <div className="table-row">
      {children.map(col => {
        let { field, ...rest } = col.props;
        const { key } = col;
        return (
          <div className="table-col" key={key}>
            {React.cloneElement(col, {
              ...rest,
              field,
              data
            })}
          </div>
        );
      })}
    </div>
  );
};

const Column = props => {
  const { field, data, width } = props;
  return (
    <div
      style={{
        width: width
      }}
      className="table-cell"
      key={data.id}
    >
      {data[field]}
    </div>
  );
};

const HeadRow = props => {
  const { children } = props;
  return (
    <div className="table-row">
      {children.map(col => {
        const { title, field, width } = col.props;
        return (
          <div className="table-col" key={field}>
            <div
              className="table-cell table-cell-head"
              style={{
                width: width
              }}
            >
              {title}
            </div>
          </div>
        );
      })}
    </div>
  );
};

const initData = [
    {
      id: 1,
      name: "Ivan",
      age: "My age is 27",
      enabled: true,
      myListValue: [
        {
          myName: "Duncan",
          myDescription: "Immortal!",
          myGroup: "Immortal",
          createDate: "2019-08-12T05:21:28Z"
        }
      ],
      lastChanged: new Date(),
      sortable: true
    },
    {
      id: 2,
      name: "Vitaly",
      age: `My age is 25\nMy age is 25\nMy age is 25\n`,
      lastChanged: new Date(),
      enabled: true,
      sortable: true
    },
    {
      id: 3,
      name: "Sergey",
      age: "My age is 29",
      enabled: true,
      myListValue: [
        {
          myName: "Duncan",
          myDescription: "Immortal!",
          myGroup: "Immortal",
          createDate: "2019-08-12T05:21:28Z"
        },
        {
          myName: "Connor",
          myDescription: "Immortal2!",
          myGroup: "MacLeods",
          createDate: "2019-08-12T05:21:28Z"
        },
        {
          myName: "John Snow",
          myDescription: "(he knows nothing)",
          myGroup: "WhiteWalkers",
          createDate: "2019-08-12T05:21:28Z"
        },
        {
          myName: "Jamie Lannister",
          myDescription: "Lannisters always pay their debts",
          myGroup: "Red castle",
          createDate: "2019-08-12T05:21:28Z"
        }
      ],
      lastChanged: new Date()
    }
  ];

ReactDOM.render(
<Table data={initData} showHeader={true} sortableConfig={{}}>
        <Column key="0" field="name" width={150} title="Name" sortable="true" />
        <Column key="1" field="age" width={150} title="AGe" sortable="true" />
      </Table>, document.getElementById('root'))
.App {
  font-family: sans-serif;
  text-align: center;
  display: flex;
  flex-wrap: wrap;
}

.table {
  border: 1px solid;
  border-bottom: none;
}

.table-row {
  width: 100%;
  border-bottom: 1px solid;
  display: flex;
}

.table-col {
  border-right: 1px solid;
}

.table-col:last-child {
  border: none;
}

.table-cell {
  white-space: pre-line;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  box-sizing: border-box;
}

.table-cell-head {
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>

<div id="root"></div>

最佳答案

Keys help React identify which items have changed, are added, or are removed.

应该为数组内的元素赋予键,以赋予它们稳定的身份,并且它们仅在周围数组的上下文中才有意义,因此两个独立的列表并不重要具有相同键的元素,只要它们在同一列表中不相等(重复的 id)。下面的代码没有问题

{
    arr.map((item,index) =>{
        //defining key only once per `arr` iteration
        const key = uniqueId(index)
        return(
            <div key={key}>
                 {
                    arr2.map((item, index) => <span key={key} />)
                 }
            </div>
        )
    })
}

请注意,该键仅在特定的父 React 元素中相关。 React 不会尝试在不同父元素之间“匹配”具有相同键的元素。 (React 不支持在不同父级之间移动主机实例而不重新创建它。) Font

请参阅docs here

关于javascript - 重用React 'key',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58485090/

相关文章:

javascript - 使用 Thunk 和 Promise 中间件链接 Promise

android - 不支持 React-native Animation.event 样式属性

javascript - 在嵌套组件中响应访问状态

javascript - 使用图像源进行文件输入

javascript - 焦点属性不适用于样式,但在焦点样式起作用之前

javascript - 功能性 React 组件中的全局作用域 prop

javascript - GoogleMap 每天显示不同的位置

javascript - 从 HTML 表中选择仅具有指定值的行?

javascript - 将元素对象与 jQuery 方法一起使用?

javascript - HighChart 时间戳突出显示现在的时间