Обновление списка React без повторного рендеринга указанного списка - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь выяснить, как визуализировать набор элементов div без повторной визуализации всего списка при добавлении нового набора.

Итак, у меня есть компонент с состоянием.Внутри указанного компонента с состоянием у меня есть функция, которая A, получает список идентификаторов записей, а B, делает запрос к каждому из этих идентификаторов записей и отправляет результаты в массив.Вот так:

getArticles = () => {
        axios.get(`${api}/topstories.json`)
             .then(items => {
                let articles = items.data;
                let init = articles.slice(0,50);
                init.forEach(item => {
                    axios.get(`${post}/${item}.json`)
                         .then(article => {
                             this.setState({ articles: [...this.state.articles, article.data]});
                    });
            })
        });
}

Затем у меня есть вторая функция, которая берет эту информацию и выводит ее в список постов.Вот так:

mapArticles = () => {
        let articles = this.state.articles.map((item, i) => {
            let time = moment.unix(item.time).fromNow();
            return(
                <section className="article" key={i}>
                    <Link className="article--link" to={`/posts/${item.id}`}/>
                    <div className="article--score">
                        <FontAwesomeIcon icon="angle-up"/>
                        <p>{item.score}</p>
                        <FontAwesomeIcon icon="angle-down"/>
                    </div>
                    <div className="article--content">
                        <div className="article--title">
                            <h1>{item.title}</h1>
                        </div>
                        <div className="article--meta">
                            {item.by} posted {time}. {item.descendants ? `${item.descendants} comments.` : null} 
                        </div>
                    </div>
                    <div className="article--external">
                        <a href={item.link} target="_blank">
                            <FontAwesomeIcon icon="external-link-alt"/>
                        </a>

                    </div>
                </section>
            )
        });
        return articles;
    }

Затем я использую {this.mapArticles()} внутри функции рендеринга для возврата соответствующей информации.

Однако, когда приложение загружает новый фрагмент данных, оноотрисовывает весь список, вызывая тонну рывков.Т.е. когда первый запрос заканчивается, он отображает первый div.Когда второй запрос заканчивается, он повторно отображает первый div и отображает второй.Когда третий запрос завершается, он повторно отображает первый и второй и отображает третий.

Есть ли способ, чтобы React распознал, что div с этим ключом уже существует, и его следует игнорировать, когда состояниеменяется и функция запускается снова?

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Если предметы прибывают в одно и то же время, подождите, пока все товары не будут выбраны, а затем просчитайте:

getArticles = () => {
    axios.get(`${api}/topstories.json`)
      .then(items => {
          let articles = items.data;
          let init = articles.slice(0, 50);
          Promise.all(init.map(item => axios.get(`${post}/${item}.json`)).then(articles => {
              this.setState({
                articles
              });
            })
          });
      }

Если вы действительно хотите визуализировать сразу после извлечения элемента, вы можете добавить служебный компонент, который будет отображаться при разрешении обещания.

class RenderOnResolve extends React.Component {
    state = null
    componentDidMount() {
      this.props.promise.then(data => this.setState(data))
    }
    render() {
      return this.state && this.props.render(this.state);
    }
  }

  // usage:

  <RenderOnResolve promise={promise} render={this.articleRenderer}/>
0 голосов
/ 22 октября 2018

Техника, которую я использую для визуализации только новой части, заключается в том, чтобы сохранить кеш-карту уже нарисованного объекта obj, поэтому в методе рендеринга я отображаю только новые входящие элементы.

Вот пример: Взгляните на https://codesandbox.io/s/wq2vq09pr7

В этом коде вы можете видеть, что список имеет массив кеша, а метод рендеринга рисует только новые массивы

class RealTimeList extends React.Component {
  constructor(props) {
    super(props);
    this.cache = [];
  }
  renderRow(message, key) {
    return <div key={key}>Mesage:{key}</div>;
  }
  renderMessages = () => {
    //let newMessages=this,props.newMessage
    let newElement = this.renderRow(this.props.message, this.cache.length);
    this.cache.push(newElement);
    return [...this.cache];
  };
  render() {
    return (
      <div>
        <div> Smart List</div>
        <div className="listcontainer">{this.renderMessages()}</div>
      </div>
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { message: "hi" };
  }

  start = () => {
    if (this.interval) return;
    this.interval = setInterval(this.generateMessage, 200);
  };
  stop = () => {
    clearTimeout(this.interval);
    this.interval = null;
  };

  generateMessage = () => {
    var d = new Date();
    var n = d.getMilliseconds();
    this.setState({ title: n });
  };

  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.start}> Start</button>
        <button onClick={this.stop}> Stop</button>
        <RealTimeList message={this.state.message} />
      </div>
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...