How to move an index of a clicked item to another component that is not a parent?

Viewed 333

Expecting effect: click <li> --> take index --> send this index to component Watch. When I click <li>, I grab the index and move it to theWatch component. However, when I click the second li it returns the index of the one I clicked for the first time. I think this is because it updates this index via componentDidMount. How can I reference this index after componentDidMount?

Todo

class Todo extends Component {
      render () {
        return (
          <div className = "itemTodos" onClick={()=> this.props.selectTodo(this.props.index)}>
          </div>
        )
      } 
    }

    export default Todo;

App

class App extends Component {
  constructor(){
    super();

    this.state {
      selectedTodoIndex: index
    }

  }

  selectTodo = (index) => {
    this.setState({
      selectedTodoIndex: index
    })
  }

  render () {
    return (
      <div>
           <ul>
      {
        this.state.todos
          .map((todo, index) =>
            <Todo
              key={index}
              index={index}
              todo={todo}
              selectTodo ={this.selectTodo}
            />
          )
      }
    </ul>
          <Watch
            selectedTodoIndex = {selectedTodoIndex}
          />
      </div>
    )
  } 
}

export default App;

Watch

class Watch extends Component {
  constructor(){
    super();

    this.state = {
      selectIndex: null
    }
  }

 componentDidMount() {
    this.setState({
      selectIndex:  this.props.selectedTodo
    });
 }


  render () {
    return (
      <div>
      </div>
    )
  } 
}
3 Answers

If i am not wrong your Todo component is in watch??. So Watch component should be like this :

render () {
    return (
      <div>
       <Todo index={this.state.selectedIndex} selectedTodo={this.props.selectedTodoIndex}/>
      </div>
    )
  } 

Here i made codesandbox of this code . Feel free to checkout and let me know if you any doubt. Code link : https://codesandbox.io/s/frosty-chaplygin-ws1zz

First of all you you use selectedTodoIndex in

<Watch
        selectedTodoIndex = {selectedTodoIndex}
      />

but it not specified in your render code. Add

const {selectedTodoIndex} = this.state;

in render function.

Second, use componentDidUpdate in Watch for update inner state on props update:

 class Watch extends Component {
  constructor(){
    super();

    this.state = {
      selectIndex: null
    }
  }

 componentDidMount() {
    this.setState({
      selectIndex:  this.props.selectedTodo
    });
 }

 componentDidUpdate (prevProps) {
    if (prevProps.selectedTodo !== this.props.selectedTodo)
        this.setState({
          selectIndex:  this.props.selectedTodo
        });
 }

  render () {
    return (
      <div>
      </div>
    )
  } 
}

There are lot of improvements to be made. But I believe what you are looking for is getDerivedStateFromProps lifeCycle method in Watch Component. So the code will be:

getDerivedStateFromProps(nextProps, prevState) {
  if(nextProps.selectedTodoIndex !== prevState.selectedTodoIndex) {
    return { selectIndex: nextProps.selectedTodoIndex }
  }
}

This will check if the selected index has changed in App Component, if yes it will update the state in Watch Component.

Related