【问题标题】:Dynamically setting height of React rendered table in Firefox differs from Chrome在 Firefox 中动态设置 React 渲染表的高度与 Chrome 不同
【发布时间】:2018-08-21 15:25:07
【问题描述】:

目前正在做一个 React 项目,使用 webpack、webpack-dev-server、热模块重载、React Router、styled-components 等

我创建了一个 Table 组件,我尝试根据父级的高度动态确定要在 Table 中呈现的行数。在 Chrome 中,这可以按预期工作,但在 Firefox 中,我发现我的所有行都被渲染,因此没有绑定在父组件中。

这是一个已知问题,还是有任何建议的解决方法,或者我的代码有什么可怕的问题?

父组件(App):

const MainContainer = styled.div`
  background-color: ${colours.white};
  border-radius: 4px;
  box-shadow: 0 0 9px 0 #dedede;
  display: flex;
  flex-wrap: wrap;
  height: 85%;
  width: 92.5%;
`;


const InnerContainer = styled.div`
  display: flex;
  flex-direction: column;
  width: calc(100% - 9.375em);
`;

const SearchAndCountPlaceholder = styled.div`
  height: 12.5%;
`;

const SidebarPlaceholder = styled.div`
  background-color: ${colours.blue.light};
  height: 100%;
  opacity: 0.12;
  width: 9.375em;
`;

const LoadMoreButtonContainerPlaceholder = styled.div`
  height: 15%;
`;

const App = () => (
  <MainContainer className="app-component">
    <SidebarPlaceholder />
    <InnerContainer>
      <SearchAndCountPlaceholder />
      <Table tableHeadings={tableHeadings} masterData={mockData} />
      <LoadMoreButtonContainerPlaceholder />
    </InnerContainer>
  </MainContainer>
);

表格组件:

const Container = styled.div`
  background-color: ${colours.white};
  height: 100%;
  overflow-x: scroll;
  padding-bottom: 1em;
  width: 100%;
`;

const StyledTable = styled.table`
  border-bottom: 2px solid ${colours.grey.lighter};
  border-collapse: collapse;
  margin: 1.25em;
  table-layout: fixed;
  width: 100%;

  & thead {
    border-bottom: inherit;
    color: ${colours.grey.lighter};
    font-size: 0.75em;
    font-weight: 700;
    line-height: 1em;
    text-align: left;
    text-transform: uppercase;

    & th {
      padding: 0.75em 1em 0.75em 1em;
      width: 7.25em;
    }

    & th:not(.Source) {
      cursor: pointer;
    }

    & span {
      color: ${colours.blue.dark};
      font-size: 1em;
      font-weight: 300;
      margin-left: 0.313em;
    }
  }

  & tbody {
    color: ${colours.grey.dark};
    font-size: 0.813em;
    line-height: 1.125em;

    & tr {
      border-bottom: 1px solid ${colours.grey.lightest};

      & td {
        padding: 1em;
      }
    }

    & .masterData {
      font-weight: 700;
    }
  }
`;

let numberOfRowsToDisplay;
const calculateNumberOfRowsToDisplay = () => {
  const tableHeight = document.querySelector('.table-component').offsetHeight;
  const rowHeight = 40; // height of row in pixels
  const numberOfRowsNotToIncludeInCalculation = 2; // header & scrollbar
  numberOfRowsToDisplay = Math.floor(
    tableHeight / rowHeight - numberOfRowsNotToIncludeInCalculation
  );
};

class Table extends Component {
  constructor(props) {
    super(props);
    this.state = { columnToSort: '' };
    this.onColumnSortClick = this.onColumnSortClick.bind(this);
  }

  componentDidMount() {
    calculateNumberOfRowsToDisplay();
  }

  onColumnSortClick(event) {
    event.preventDefault();
    const columnToSort = event.target.className;
    this.setState(prevState => {
      if (prevState.columnToSort === columnToSort) {
        return { columnToSort: '' };
      }
      return { columnToSort };
    });
  }

render() {
  const { tableHeadings, masterData } = this.props;
  const { columnToSort } = this.state;

  const upArrow = '⬆';
  const downArrow = '⬇';

  return (
    <Container className="table-component">
      <StyledTable>
        <thead>
          <tr>
            {tableHeadings.map(heading => (
              <th
                className={heading}
                key={heading}
                onClick={this.onColumnSortClick}
              >
                {heading}{' '}
                {heading !== 'Source' ? (
                  <span>
                    {heading === columnToSort ? upArrow : downArrow}
                  </span>
                ) : null}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {masterData &&
            masterData.slice(0, numberOfRowsToDisplay).map(data => {
              const dataKey = uuidv4();
              return (
                <tr className="masterData" key={dataKey}>
                  <td>Master</td>
                    {Object.values(data).map(datum => {
                      const datumKey = uuidv4();
                      return <td key={datumKey}>{datum}</td>;
                    })}
                </tr>
              );
              })}
          </tbody>
        </StyledTable>
      </Container>
    );
  }
}

提前致谢!

【问题讨论】:

  • 你试过用 refs 代替直接访问 dom 吗? reactjs.org/docs/refs-and-the-dom.html
  • 感谢您的建议。我已经快速阅读了文档并快速解决了问题,但我不确定这对我是否有用(或者我做错了什么!)我认为问题在于我正在尝试生成第二个整数以传递给 .slice(),并且在 ref 上调用 offsetHeight 似乎总是返回 undefined

标签: javascript reactjs google-chrome firefox offsetheight


【解决方案1】:

也许不是我一直在寻找的答案,但最后我将动态numberOfRowsToDisplay 设置为组件状态的一部分;这给了我正在寻找的 UI 结果

【讨论】:

    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 2012-10-04
    • 2019-12-15
    • 2018-05-21
    • 2014-05-03
    • 1970-01-01
    相关资源
    最近更新 更多