4

I'm trying to create a todo list where after you finish one task,
only then will the next task be enabled (to tick as finished).

Here is what I have so far:

/** @jsx React.DOM */
$(function(){
var tasks = [
  {title: "Wake up"},
  {title: "Eat dinner"},
  {title: "Go to sleep"}
];
var Task = React.createClass({
    getInitialState: function(){
        return {locked:true, done:false}  
    },
    handleClick: function(e){
        this.setState({done: !this.state.done});  
        var selector = '.toggle[data-order="'+(this.props.order+1)+'"]';
        this.setState({locked: true})
        console.log(selector)
        console.log($(selector).removeAttr("disabled"))

    },
    render: function() {

      var locked;
      //Fix first task to not be disabled
      if(this.props.order == 0 && this.state.done === false)
        locked = false;
      else
        locked = this.state.locked;
      var done = this.state.done ? "Done":"Not done";
      var classView = "task" + (this.state.done ? " done":" not-done");
      return (
          <div class="todo well well-sm" class={classView}>
            <span class="description">{this.props.title}</span>
            <button type="button" onClick={this.handleClick} data-order={this.props.order} disabled={locked} class="toggle btn btn-default btn-xs pull-right">
              <span class="glyphicon glyphicon-unchecked"></span>&nbsp;Done
            </button>
          </div>
      );
    }
});
var TaskList = React.createClass({
  render: function(){
    var i = -1;
    var taskNodes = this.props.data.map(function (task) {
      return <Task title={task.title} order={++i} />;
    });
    return (
      <div class="task-list">
       {taskNodes}
      </div>
    );
  }
});
var Guider = React.createClass({
  render: function(){
    return (
      <div>
        <TaskList data={this.props.data} />
      </div>
    );
  }
});
React.renderComponent(<Guider data={tasks} />, document.body);
});

The next buttons are still not disabled, and I feel that I'm doing something wrong in general (not in accordance with the react "zen").

Btw: How can I change the state for a dom element without the user triggering it? is there any id I should use?

2
  • I would declare handleClick inside TaskList and pass it as props to Task and call that. This will allow you to change state of other Tasks. Commented Aug 25, 2013 at 19:04
  • You shouldn't define everything in DOMReady like that, just the instantiation of your code. This will make it run faster! Commented Mar 27, 2015 at 3:22

1 Answer 1

7

If you initiate the data into non-root component, it becomes hard to update other components. So I prefer keeping data into root component, Then pass a click handler as props. Now you'll have access to that handler inside non-root component. Calling that will update root component and so the other non-root components.

Here's working jsFiddle - http://jsfiddle.net/ammit/wBYHY/5/

Example -

var Task = React.createClass({
  handleClick: function (e) {
    // Passing order of task
    this.props.clicked(order);
  },
  render: function () {
    return ( <button type="button" onClick={this.handleClick}></button> );
  }
});


var TaskList = React.createClass({
  getInitialState: function(){
    // initiate tasks here
  },
  whenClicked: function(order){
    // Revise the tasks using `order`
    // Finally do a setState( revised_tasks );
  },
  render: function(){
    return ( <Task clicked={this.whenClicked} /> );
  }
});
Sign up to request clarification or add additional context in comments.

2 Comments

When triggering 'this.props.clicked(order);' will it call 'whenClicked' ? and how after that can I enable the next task? (how can I access that dom element?)
I'd just add that I usually prefer to keep the naming schemes for things the same as in-built elements in react. So for example rather than using the prop clicked it would be better if it was called onClick for consistency. Then you always know if it's a built-in or custom component that onClick={this.handler} is what you need to do. There's no conflicts with using the same naming convention that occur.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.