0
votes

I'm creating a Todo app. Although I'm able to create todos and display them but now with each todo I created a input tag which should change the name of todo.

Here is my container component index.js:

import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";

class App extends Component {
  state = {
    todoItem: [],
    todoText: ""
  };
  addTodoHanlder = event => {
    let todoValue = this.state.todoText;
    this.setState({
      todoItem: [...this.state.todoItem, todoValue]
    });
    this.clearTodoText();
    todoValue = "";
  };

  clearTodoText() {
    this.setState({ todoText: "" });
  }

  handleChange = event => {
    this.setState({ todoText: event.target.value });
  };
  todoNameChangeHandler = event => {
    let todoVal = event.target.value;
    this.state.todoItem.map(todo => {
      this.setState({
        todoItem: todoVal
      });
    });
  };

  render() {
    return (
      <div>
        <input
          type="text"
          placeholder="Enter Todo"
          value={this.state.todoText}
          onChange={this.handleChange}
        />
        <button onClick={this.addTodoHanlder}>AddTodo</button>
        <Hello
          todos={this.state.todoItem}
          changed={this.todoNameChangeHandler}
        />
      </div>
    );
  }
}
render(<App />, document.getElementById("root"));

Here is my Hello.js component to display todos:

import React from "react";

const hello = props => {
  return (
    <div>
      <ul>
        {props.todos.map((todo,index) => {
          return (
          <div>
            <p key={index}>{todo}</p>
            <input type="text" onChange={props.changed} />
          </div>
  )
        })}
      </ul>
    </div>
  );
};

export default hello;

Can someone help me out how can this be done? I used todoNameChangeHandler method to change the name of todos and I'm getting this error: TypeError props.todos.map is not a function hello /src/Hello.js:7:21 4 | return ( 5 | 6 |

7 | {props.todos.map((todo,index) => { | ^ 8 | return ( 9 | 10 | {todo}

1
why todoNameChangeHandler have loop with state; because todoItem is array which is changing to string after setStatePiyush Bhati

1 Answers

0
votes

What happen is as soon as todoNameChangeHandler was called, the type of todoItem was changed from array to string that's why todos.map throws you an error.

You can change your todoNameChangeHandler function to something like this to just target the element you want to update.

todoNameChangeHandler = (event, targetIndex) => {
  let todoVal = event.target.value;
  this.setState(prevState => ({
    todoItem: prevState.todoItem.reduce(
      (accum, current, currentIndex) => {
        if (currentIndex === targetIndex) { // will look for the matching index
          return [...accum, todoVal]; // then replace the old value with the new value
        } else {
          return [...accum, current]; // otherwise just keep the old one
        }
      },
      []
    )
  }));
}

just make sure you pass the index of the array element from <hello /> to <App />.