Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React组件在重新渲染时滚动回顶部_Reactjs - Fatal编程技术网

Reactjs React组件在重新渲染时滚动回顶部

Reactjs React组件在重新渲染时滚动回顶部,reactjs,Reactjs,我的React组件有这个问题,我无法解决。每次重新渲染时,它都会回滚到顶部。而且,我也不明白为什么它首先要重新渲染。基本上,我有祖父母、父母和孙子女。孙辈有一个单击事件,显示祖父母的另一个孩子(如果有意义的话)。该单击事件会执行一些操作,但它会导致祖父母的重新渲染,从而导致父组件滚动到顶部。我将加入我的代码,希望能澄清我在这里说的话。只是想提供一些背景 因此,主要问题是滚动到顶部。如果我们能够弄清楚它为什么要重新渲染并停止渲染,那将是一个额外的好处 祖父母(StaticLine.js): 如果需

我的React组件有这个问题,我无法解决。每次重新渲染时,它都会回滚到顶部。而且,我也不明白为什么它首先要重新渲染。基本上,我有祖父母、父母和孙子女。孙辈有一个单击事件,显示祖父母的另一个孩子(如果有意义的话)。该单击事件会执行一些操作,但它会导致祖父母的重新渲染,从而导致父组件滚动到顶部。我将加入我的代码,希望能澄清我在这里说的话。只是想提供一些背景

因此,主要问题是滚动到顶部。如果我们能够弄清楚它为什么要重新渲染并停止渲染,那将是一个额外的好处

祖父母(StaticLine.js):

如果需要更多信息或更多代码,请告诉我。如果您有任何见解,我们将不胜感激。

const OrderColWithRef=React.forwardRef((props,ref)=>(
));
将其作为顶级功能移到
静态行
之外

发生了什么事 React足够聪明,可以避免在只有部分Dom发生更改时重新创建html元素和装载内容。如果只有一个道具更改,它将保留该元素并仅更改其值等。这是通过比较
元素来完成的。键入

有效的做法是在每个渲染上创建一个新的
OrderColWithRef
函数,因为它是一个局部函数,所以类型不相等。每当
StaticLine
中的任何内容发生更改时,React将卸载并重新装载一个新的html元素

永远不要嵌套组件声明。在函数中声明组件唯一有效的情况是HOC,即使这样,HOC函数本身也不是有效的元素,只是它的返回值是有效的


希望这能解决问题。

您是否尝试过使用
getSnapshotBeforeUpdate()
?据官方称:

在最近呈现的输出提交到DOM之前调用。它使您的组件能够在可能发生更改之前从DOM中捕获一些信息(例如滚动位置)

基本上,您可以在重新渲染之前访问当前的滚动位置,从
getSnapshotBeforeUpdate()返回
在组件更新之后,使用可以访问从
getSnapshotBeforeUpdate()
返回的值,并将滚动位置设置为重新渲染之前的位置。借用官方文件中的示例:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}
类滚动列表扩展了React.Component{
建造师(道具){
超级(道具);
this.listRef=React.createRef();
}
getSnapshotBeforeUpdate(prevProps,prevState){
//我们是否在列表中添加新项目?
//捕获滚动位置,以便稍后调整滚动。
if(prevProps.list.length

我强烈建议使用软件包让您了解组件呈现的原因。

我的问题是将接收新数据的东西作为组件处理,而不是作为返回组件的函数处理


更改为
{newsList()}
成功了。

您尝试过用React.memo包装组件吗?我没有,那是什么样子?它是做什么的?我把它添加到我的StaticLine组件的底部<代码>常量MemoizedStaticLine=React.memo(StaticLine);导出默认的MemoizedStaticLine仍然滚动到顶部。@dmikester1您尝试过我的解决方案吗?你的问题解决了吗?我确实尝试了为什么你渲染插件,但在日志中没有看到任何有用的东西。由于我使用的是功能组件,我认为我不能使用
getSnapshotBeforeUpdate()
,但我无权访问StaticLine之外的lineTitle、lineID或订单?为什么不将它们作为道具传递给
OrderColWithRef
import React from 'react';
import PropTypes from 'prop-types';
import StaticOrder from '../order/StaticOrder';
import '../../scss/App.scss';
import { useGlobalSpinnerContext } from '../../context/GlobalSpinnerContext';

const StaticOrderColumn = (props) => {
    const { title, lineID, orders } = props;

    const isGlobalSpinnerOn = useGlobalSpinnerContext();

    const sortedOrdersIDs = orders
        .filter((o) => o.lineNum === lineID)
        .sort((a, b) => a.linePosition - b.linePosition)
        .map((o) => o.id);

    return (
        <div id={'line-0'} className={'col order-column'}>
            <header className={'text-center title'}>
                {title}{' '}
                {sortedOrdersIDs.length > 0 && (
                    <span> ({sortedOrdersIDs.length})</span>
                )}
            </header>
            <div className={'orders'}>
                {orders &&
                    sortedOrdersIDs &&
                    sortedOrdersIDs.map((orderID, index) => {
                        const order = orders.find((o) => o.id === orderID);
                        return (
                            <StaticOrder
                                key={orderID}
                                order={order}
                                index={index}
                            />
                        );
                    })}
                {!sortedOrdersIDs.length && !isGlobalSpinnerOn && (
                    <h3>There are no orders on this line.</h3>
                )}
            </div>
        </div>
    );
};

StaticOrderColumn.propTypes = {
    title: PropTypes.string.isRequired,
    lineID: PropTypes.number.isRequired,
    orders: PropTypes.array.isRequired,
    ref: PropTypes.instanceOf(Element).isRequired
};

export default StaticOrderColumn;
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import '../../scss/App.scss';
import { getFormattedDate } from '../../utils/utils';
import { useGlobalActiveOrderActionsContext } from '../../context/GlobalActiveOrderContext';
import { useGlobalShowDetailsActionsContext } from '../../context/GlobalShowDetailsContext';
// import { stringTrunc } from '../../utils/utils';

const MyOrder = styled.div`
    background-color: #193df4;
    transition: background-color 1s ease;
`;

const devMode = true;
// const devMode = false;

const StaticOrder = (props) => {
    const {
        id,
        item,
        desc,
        cust,
        palletsOrd,
        bagID,
        chemicals,
        totalBagsUsed,
        linePosition,
        palletsRem,
        palletCount,
        requestDate,
        orderNumber,
        comments
    } = props.order;

    const setActiveOrder = useGlobalActiveOrderActionsContext();
    const setShowDetails = useGlobalShowDetailsActionsContext();

    const orderID = id + '';

    // show the details section when user clicks an order
    // THIS IS WHERE THE ISSUE IS HAPPENING, WHEN THE ORDER IS CLICKED,
    // THIS FUNCTION RUNS AND THE StaticLine COMPONENT RE-RENDERS AND THE StaticOrderColumn SCROLLS TO THE TOP
    const showDetails = (orderID) => {
        setActiveOrder(parseInt(orderID, 10));
        setShowDetails(true);
    };

    return (
        <MyOrder
            id={orderNumber}
            className={'order static'}
            onClick={(e) => showDetails(orderID, e)}
        >
            {/*<div className={'orderID'}>{id}</div>*/}
            <p className={'item-number'}>
                {item !== '' ? `Item Number: ${item}` : ''}
            </p>
            <p>{desc !== '' ? `NPK: ${desc}` : ''}</p>
            <p>{cust !== '' ? `Customer: ${cust}` : ''}</p>
            <p>
                {palletsOrd !== '' ? `Pallets Ordered: ${palletsOrd}` : ''}
            </p>
            <p>{bagID !== '' ? `Bag ID: ${bagID}` : ''}</p>
            <p>{chemicals !== '' ? `Chemical : ${chemicals}` : ''}</p>
            <p>
                {requestDate !== ''
                    ? `Request Date: ${getFormattedDate(new Date(requestDate))}`
                    : ''}
            </p>
            {devMode && (
                <>
                    <div className={'id-line-num-pos'}>
                        <p>OrderID: {orderNumber}</p>
                    </div>
                </>
            )}
            <div className={'total-bags'}>Total Bags: {totalBagsUsed}</div>
            <div className={'pallets-remaining'}>
                Pallets Left: {palletsRem}
            </div>
            <div className={'pallets-done'}>
                Pallets Done: {palletCount}
            </div>
            <div className={'line-position'}>{linePosition + 1}</div>
            {comments.length > 0 && (
                // bunch of SVG code
            )}
        </MyOrder>
    );
};

StaticOrder.propTypes = {
    order: PropTypes.object,
    id: PropTypes.number,
    index: PropTypes.number,
    title: PropTypes.string,
    orderID: PropTypes.string
};

export default StaticOrder;
{orderType === 'completed' && showDetails && (
  <OrderButtons
    setLineID={setLineID}
    setOrders={setOrders}
    orders
    lineNum={lineID}
  />
)}
class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}