Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.js: How do you change the position of a Component item

How do you change the position of a Component item in React?

Unless I've misunderstood it, React orders list items by key, which is represented in the DOM by data-reactid, but I don't know how to modify the key of components on the page.

i.e. How do you grab the component, change it's key, and then fire a render so that the reordered list renders in the order you've set?

e.g. in the following code example, when the Click me link is clicked, the first list item would be swapped with the last list item.

Ideally, this functionality would allow you to dynamically reorder/relocate any component on the page without changing the order of components in the render method.

Here is a link to the repo where the full project is located: https://github.com/bengrunfeld/gae-react-flux-todos

var TodoBox = React.createClass({
  render: function(){
    return (
      <div className="todo-container">
        <h4>GAE React Flux Todos</h4>
        <TodoList data={this.state.data} />
      </div>
    )
  }
});

var TodoList = React.createClass({
  changePosition: function(e){
    // Change position of list item (e.g. to top/certain position/end of list)
  },
  render:function(){
    var todoNodes = this.props.data.map(function(todo) {
      return (
        <Todo key={todo.id} id={todo.id}>
          {todo.todoText}
        </Todo>
      );
    });
    return (
      <form className="todoList">
        {todoNodes}
        <a onClick={this.changePosition}>Click me</a>
      </form>
    )
  }
});

var Todo = React.createClass({
  render:function(){
    return (
      <div className="todoItem">
        <input type="text" className={this.props.id} onChange={this.checkInput} defaultValue={this.props.children} ref="todoItem"/>
      </div>
    )
  }
});
like image 491
Ben Avatar asked Mar 12 '15 21:03

Ben


People also ask

How do I change position of element in React?

Approach: We are going to use following steps: Assume the position of our element is 0 on x-coordinate and 0 on y-coordinate. Then we will add/subtract some value from x/y coordinate depending on the direction we are moving.

How do you position a div in a specific coordinates React?

You can set the position of any DOM-Element with position: absolute; , top : yCoordinate and left : xCoordinate css attributes. You can then set those in any shape or form and the desired result should be visible.

Can a component change its props?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.


1 Answers

The key prop is not used to order the element, but to reconciliate it between different render calls. Elements with the same key will not be re-rendered but rather diffed against each other in order to update the DOM optimally. See Reconciliation

If you want to reorder elements, you need to change their position in your JSX or in the element array you pass as children in your render method (todoNodes).

In your case, you could make a copy of this.props.data in the TodoList component state, then update that copy in your changePosition method with something like this.setState({data: reorderedData}). A good place to make that copy would be in getInitialState.

The render method of your TodoList would then be called again, and you would map over your newly reordered this.state.data to create an array of Todo elements ordered to your liking.

However, be aware that props in getInitialState is an anti-pattern. Since your data lives in the state of your TodoBox component, a way to avoid this would be to have your TodoList component call this.props.onReorder(reorderedData) in its changePosition method. Your TodoBox component could then pass an event handler to its TodoList child, and update its state with the new data whenever this handler is called.

var TodoBox = React.createClass({
  handleReorder: function(reorderedData) {
    this.setState({data: reorderedData});
  },

  render: function(){
    return (
      <div className="todo-container">
        <h4>GAE React Flux Todos</h4>
        <TodoList data={this.state.data} onReorder={this.handleReorder} />
      </div>
    )
  }
});

var TodoList = React.createClass({
  changePosition: function(e){
    // Change position of list item (e.g. to top/certain position/end of list)
    // Create a copy of this.props.data and reorder it, then call
    // this.props.onReorder to signal to the parent component that
    // the data has been reordered
    this.props.onReorder(reorderedData);
  },

  render:function() {
    var todoNodes = this.props.data.map(function(todo) {
      return (
        <Todo key={todo.id} id={todo.id}>
          {todo.todoText}
        </Todo>
      );
    });
    return (
      <form className="todoList">
        {todoNodes}
        <a onClick={this.changePosition}>Click me</a>
      </form>
    )
  }
});
like image 165
Alexandre Kirszenberg Avatar answered Sep 28 '22 14:09

Alexandre Kirszenberg