ReactFix
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • React
  • React Native
  • Programming
  • Object Oriented Programming

Thursday, October 27, 2022

[FIXED] How do I get a value from a child in grand parent?

 October 27, 2022     callback, nested, reactjs   

Issue

EDIT : Solution found. I forgot to had a prop 'handleCallback' when creating my subList

 renderSubList() {
        let subList = this.props.item.subList
        if (subList === undefined)
            return
        subList = subList.map(
            item =>
            <Item key={item.id} item={item} handleCallback={...} /> <== HERE
            )
          return subList

    }

I'm a bit new with Reactjs so I'm trying to do a custom TODO list with task and subtask. I'm facing a problem when I want to delete a subtask telling me that my callback isn't a function. I have no issue when deleting a task. I don't really understand my problem, is it a callback problem or maybe my data structure?

P.S: this is my first post, it is a bit ugly.

github repo for the code : https://github.com/JohnPAfr/todolist

So my data looks like this:

todoList:[
        {id:0, task:'tâche #1', subList: [
            {id:0, parent:0, task:'sous-tâche #1'},
            {id:1, parent:0, task:'sous-tâche #2'},
            {id:2, parent:0, task:'sous-tâche #3'},
        ]},
        {id:1, task:'tâche #2'},
        {id:2, task:'tâche #3'},
        {id:3, task:'tâche #4'},
]

My problem comes when I want to delete an item from the subList.

I map my 'todoList' from my state and make a TodoItem for each object in my list.

class TodoBis extends Component {
  constructor(props){
    super(props)
    this.state = {
      todoList: ... (see above)
    }

    this.renderTodoItems = this.renderTodoItems.bind(this)
    this.handleAdding = this.handleAdding.bind(this)
    this.handleDelete = this.handleDelete.bind(this)

  }

  renderTodoItems() {
    let list = this.state.todoList
    list = list.map(
      item =>
      <TodoItem key={item.id} item={item} handleDelete={this.handleDelete}/>
      )
    return list
  }

  handleAdding(input) {...}

  handleDelete(item) {...}
  
  render() {
    return (
      <div>
        <AddBar handleAdding={this.handleAdding} />
        {this.renderTodoItems()}
      </div>
    );
  }
}

TodoItem create an item with subitems

class TodoItem extends Component {
    constructor(props) {
        super(props)

        this.renderSubList = this.renderSubList.bind(this)
        this.handleCallback = this.handleCallback.bind(this)

    }

    renderSubList() {
        let subList = this.props.item.subList
        if (subList === undefined)
            return
        subList = subList.map(
            item =>
            <Item key={item.id} item={item} />
            )
          return subList

    }

    handleCallback(item) {
        this.props.handleDelete(item)
    }
  
  render() {
      const {item} = this.props
    return (
      <div>
          <Item key={item.id} item={item} handleCallback={() => this.props.handleDelete(item)} />
          <div className={(item.subList === undefined) ? '' : 'subList'}>
            {this.renderSubList()}
          </div>
      </div>
    );
  }
}

Finally I have Item which displays my data

class Item extends Component {

    render() {
        const {item} = this.props
        const task = item.task
        return (
            <div onClick={() => this.props.handleCallback(this.props.item)} className='item-container'>
                <span>{task}</span>
            </div>
        )
    }
}

I expect to delete the correct task or subtask when Item is clicked.


Solution

This code confuses me:

handleCallback() {
        const handleCallback = this.props.handleCallback
        const item = this.props.item
        console.log(item)
        handleCallback(item)
    }

<div onClick={() => this.handleCallback(item)} className='item-container'>
                <span>{task}</span>
            </div>

Why don't you change it to this:

<div onClick={() => this.props.handleCallback(this.props.item)} className='item-container'>
                <span>{task}</span>
            </div>

The second handleCallback is not needed, it does no additional logic.



Answered By - Gh05d
Answer Checked By - - Mary Flores (ReactFix Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Newer Post Older Post Home

Featured Post

Is Learning React Difficult?

React is difficult to learn, no ifs and buts. React isn't inherently difficult to learn. It's a framework that's different from ...

Total Pageviews

Copyright © ReactFix