programing

대응: 모든 항목을 재작성하지 않고 목록의 항목 하나를 업데이트합니다.

kingscode 2023. 3. 22. 22:41
반응형

대응: 모든 항목을 재작성하지 않고 목록의 항목 하나를 업데이트합니다.

예를 들어 1000개의 아이템 리스트가 있다고 칩시다.React로 렌더링하면 다음과 같이 됩니다.

class Parent extends React.Component {
  render() {
    // this.state.list is a list of 1000 items
    return <List list={this.state.list} />;
  }
}

class List extends React.Component {
  render() {
    // here we're looping through this.props.list and creating 1000 new Items
    var list = this.props.list.map(item => {
      return <Item key={item.key} item={item} />;
    });
    return <div>{list}</div>;
  }
}

class Item extends React.Component {
  shouldComponentUpdate() {
    // here I comparing old state/props with new
  }
  render() {
    // some rendering here...
  }
}

list map()이 비교적 길면 10~20ms 정도 걸리고, 인터페이스의 약간의 지연을 알 수 있습니다.

업데이트만 필요한 경우 매번 1000개의 React 개체를 재생하지 못하도록 할 수 있습니까?

관리 할 수 에 의해, 「」는 「」의 「관리 라이브러리」를 사용해 주세요.Parent이 묘연하다this.state.list의 => 고고고의의List 「」가 발생했을 때만 한다.Item을 사용하다 개인 ★★★★★★★★★★★★★★★★★★★★★★★.Item는 갱신되면 다시 갱신됩니다.

, '우리'를 사용한다고 .redux.

코드는 다음과 같습니다.

// Parent.js
class Parent extends React.Component {
  render() {        
    return <List />;
  }
}
// List.js
class List extends React.Component {
  render() {        
    var list = this.props.list.map(item => {
      return <Item key={item.key} uniqueKey={item.key} />;
    });
    return <div>{list}</div>;
  }
}

const mapStateToProps = (state) => ({
  list: getList(state)
});

export default connect(mapStateToProps)(List);
 
// Item.js
class Item extends React.Component {
  shouldComponentUpdate() {
  }
  render() {
  }
}

const mapStateToProps = (state, ownProps) => ({
  item: getItemByKey(ownProps.uniqueKey)
});

export default connect(mapStateToProps)(Item);

.getList ★★★★★★★★★★★★★★★★★」getItemByKey.

은, 으 with신신 with.List추가되었을 때 되었을 때 .item.key안 되는 것)

편집:

처음에 제안했던 내용은 렌더링된 목록의 효율성 개선 가능성에 대해서만 다루었을 뿐 목록 변경에 따른 컴포넌트 재렌더링 제한에 대한 질문은 다루지 않았습니다.

첫 번째 질문에 대한 명확한 해답은 @shiaofan2406의 답변을 참조하십시오.


긴 목록을 보다 효율적이고 쉽게 렌더링할있는 라이브러리:

무한 반응

리액트 가상화

데이터를 변경할 때 리액트 기본 조작은 모든 하위 구성요소를 렌더링하고 가상 돔을 생성하여 렌더링해야 하는 구성요소를 판단합니다.

따라서 리액션을 할 수 있는 컴포넌트는 1개뿐입니다.시간을 절약할 수 있습니다.

하시면 됩니다.shouldComponentsUpdate목록 구성 요소에 있습니다.

이 함수에서 false가 반환되는 경우 react는 판단할 vital dom을 생성하지 않습니다.

는 이렇게 됩니다.[{name: 'name_1'}, {name: 'name_2'}]

class Item extends React.Component {
  // you need judge if props and state have been changed, if not
  // execute return false;
  shouldComponentUpdate(nextProps, nextState) { 
    if (nextProps.name === this.props.name) return false;

    return true;
  }
  render() {
    return (
      <li>{this.props.name}</li>
   )
  }
}

리액션은 변경된 컴포넌트를 렌더링합니다.따라서 한 항목의 데이터만 변경하면 다른 항목이 렌더링되지 않습니다.

몇 가지 작업을 수행할 수 있습니다.

  1. 때 가동 상태로 "NODE_ENV").NODE_ENV=production npm run build또는 이와 유사합니다.ReactJS는 JS가 반응할 때 많은 안전 합니다.NODE_ENVPropType 。이 기능을 끄면 리액트 렌더링 성능이 2배 이상 향상되고 프로덕션 구축에 필수적입니다(개발 중에는 사용하지 않지만 안전 검사를 통해 버그를 방지할 수 있습니다).이 정도면 지원해야 할 항목 수에 충분할 수 있습니다.
  2. 요소가 스크롤 가능한 패널에 있고 일부 요소만 볼 수 있는 경우 요소의 가시적인 하위 집합을 렌더링하도록만 설정할 수 있습니다.이것은 물건의 높이가 고정되어 있을 때 가장 쉽다.기본 접근법은 다음과 같습니다.firstRendered/lastRendered소품 목록 상태(처음에는 포함, 마지막에는 제외)에 따라 달라집니다.List.render, 필러를 공백으로 만듭니다.div(또는tr적절한 높이(해당하는 경우)의 경우firstRendered * itemHeight렌더링한 아이템의 범위)[firstRendered, lastRendered)그 후 나머지 높이를 가진 다른 주입구 div)(totalItems - lastRendered) * itemHeight). 필러와 아이템에 고정키를 입력해 주세요.그런 다음 스크롤 가능한 div에서 onScroll을 처리하고 렌더링할 올바른 범위를 파악하면 됩니다(일반적으로 위와 아래에서 적절한 오버랩을 렌더링하고 가장자리에 가까워졌을 때 setState만 트리거하여 범위를 변경할 수 있습니다).더 엉뚱한 대안은 당신만의 스크롤바를 렌더링하고 구현하는 것이다(Facebook의 Fixed DataTable이 제 생각에 - https://facebook.github.io/fixed-data-table/)).https://react.rocks/tag/InfiniteScroll에는 이 일반적인 접근법의 많은 예가 있습니다.
  3. 상태 관리 라이브러리를 사용하여 으로 로드 방식을 사용합니다.대규모 앱의 경우 이는 필수적입니다.항목' 상태를 위에서 아래로 넘기는 대신, 각 항목이 '전역' 상태(기존 플럭스처럼)에서 또는 반응 컨텍스트(현대 플럭스 구현, MobX 등)를 통해 자체 상태를 검색하도록 하십시오.이렇게 하면 항목이 변경될 때 해당 항목만 다시 렌더링하면 됩니다.

모든 렌더가 구성요소 목록에서 반복되지 않도록 하는 한 가지 방법은 렌더 함수 외부에서 수행하여 변수에 저장하는 것입니다.

class Item extends React.Component {
    shouldComponentUpdate(nextProps, nextState) {
        return this.props.item != nextProps.item;
    }

    render() {
        return <li>{this.props.item}</li>;
    }
}

class List extends React.Component {
    constructor(props) {
        super(props);
        this.items = [];
        this.update = this.update.bind(this);
    }

    componentWillMount() {
        this.props.items.forEach((item, index) => { this.items[index] = <Item key={index} item={item} /> });
    }

    update(index) {

        this.items[index] = <Item key={index} item={'item changed'} />
        this.forceUpdate();
    }

    render() {
        return <div>
            <button onClick={() => { this.update(199); }}>Update</button>
            <ul>{this.items}</ul>
        </div>
    }
}

언급URL : https://stackoverflow.com/questions/33080657/react-update-one-item-in-a-list-without-recreating-all-items

반응형