Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS component rendering and how to append elements to the div the component is mounted on

Tags:

reactjs

I'm having this use case where there is a 'load more' button on the page to fetch more items from an API endpoint, and so I want these items to get appended to the DOM when they arrive. The thing is that the HTML page that is served by the web server comes with some extra list items (as seen below) within the same item-list div container I mount my React component, with empty data/props, on page load.

<div class="item-list">
  <div class="item-list__child-item"></div>
  <div class="item-list__child-item"></div>
  ...
  <div class="item-list__child-item"></div>
</div>

My assumption is that if I handle this in the ReactJS way, as soon as I fetch more items from the server (REST) and append those items to an 'itemList' state array, react will somehow replace all of the content that holds that 'item-list' div where the component was mounted on.

A quick workaround that I'm thinking would work and that it doesn't rely on the isomorphic stuff and pre-rendering the react component on the server, is to create a separate sibling div having the same div class name 'item-list' and adding an id attribute to mount the component on, so the resulting HTML would go like:

<div class="item-list">
  <div class="item-list__child-item"></div>
  <div class="item-list__child-item"></div>
  ...
  <div class="item-list__child-item"></div>
</div>

<div class="item-list" id="react-component-name"></div>

Maybe there is a cleaner way to do it without getting into the isomorphic stuff, or maybe I'm not understanding the React concept and how it works. Anyways will appreciate any directions you may have on this.

like image 861
dzv3 Avatar asked Sep 07 '15 12:09

dzv3


People also ask

Does component did mount run after render?

componentDidMount() method As the name suggests, after all the elements of the page is rendered correctly, this method is called. After the markup is set on the page, this technique called by React itself to either fetch the data from An External API or perform some unique operations which need the JSX elements.

What does it mean when a React component is mounted?

Mounting refers to the initial page loading when your React component is first rendered. From React documentation for Mounting: componentDidMount: Invoked once, only on the client (not on the server), immediately after the initial rendering occurs.

How does component render React?

React renders HTML to the web page by using a function called render(). The purpose of the function is to display the specified HTML code inside the specified HTML element. In the render() method, we can read props and state and return our JSX code to the root component of our app.


1 Answers

OK, your question wasn't clear on this, but the data that is represented by what was generated in the HTML will be entirely different from the data that you will be getting via AJAX.

There's a simple solution to this. Instead of creating an entirely new DOM element that will be adjacent to your original DOM layout, what you will do is grab the data that was already there, store it into an array, and append the new data that you will grab via AJAX into that Array. This way, you will reap the benefit of React's DOM diffing. Why is it useful? Maybe you want to let the user sort the data, or interact with the data directly, while it will remain in full control of a parent React component.

So anyways, take a look at this fiddle: https://jsfiddle.net/x4jjry04/3/. It's based on Paul Booblic's fiddle.

var Page = React.createClass({ 
  getDefaultProps: function () {
    return {
      items: []
    }
  },
  getInitialState : function(){
    return{
      items : this.props.items
    }
  },
  componentDidMount: function () {
    // Mimics an AJAX call, but replace this with an actial AJAX call.
    setTimeout(function () {
      var dataFromAjax = ['one', 'two', 'three'];
      this.setState({
        items: this.state.items.concat(dataFromAjax)
      });
    }.bind(this));
  },
  addClick : function(){
    this.state.items.push("more");
    this.forceUpdate();
  },
  render : function(){
    return <div>{this.state.items.map(function(item){return <div className="bla-bla-class">{item}</div>})}<br/><div onClick={this.addClick}>ADD</div></div>;
  }
});

var elements = document.querySelectorAll('.item-list__child-item');

var initialvalues = Array.prototype.slice
  .call(elements)
  .map(function (div) {
    return div.innerHTML;
  });

React.render(<Page items={initialvalues} />, document.body);
like image 198
Sal Rahman Avatar answered Sep 30 '22 13:09

Sal Rahman