TodoApp - 使用索引

时间:2018-04-04 18:05:12

标签: reactjs

我试图通过点击li来切换单个待办事项。

我最初通过在Todo类组件上建立一个状态并从那里修改它来做到这一点,从那时起我将状态移动到TodoApp组件。

我可以通过指定1的索引号来切换单个待办事项,它将切换todo与索引1,但是我似乎无法弄清楚如何获取被点击的li元素的索引。我的li元素嵌套在Todo组件中。

如果我将索引保留为(i)inClick = {()=> this.props.toggleTodo(i)} ,我收到错误,

./ SRC / index.js     第12行:'i'未定义为no-undef

如何正确地将我的List组件中的索引传递给正在Todo组件中执行的 this.props.toggleTodo()函数?

任何帮助将不胜感激!

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';

// initializing todo
class Todo extends React.Component {
    render() {
        return (
            <ul>
                <li className="todo" 
                    onClick={() => this.props.toggleTodo(i)}>
                    <span className="btn-completed" style={{color: this.props.completed ? '#99cc99' : '#fafafa'}}>{'\u{2714}'}</span>
                    <span style={{textDecoration: this.props.completed ? 'line-through' : 'none'}}>{this.props.text}</span>
                    <span className="btn-delete" onClick={() => this.props.onClick(this.props.id)} >{'\u{2716}'}</span>
                </li>
            </ul> 
        )
    }
}

// initializing list of todos
const List = (props) => (
    <div>
        {props.todos.map((todo, i) => <Todo key={todo.id} onClick={props.onClick} toggleTodo={props.toggleTodo} {...todo}/>)}
    </div>
)

// initializing form
const Form = (props) => (
    <form onSubmit={props.onSubmit}>
        <input type="text" autoFocus required placeholder="Enter Todo..."
            value={props.value}
            onChange={props.onChange}
        />
    </form>
)

// initializing main app
class TodoApp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            inputText: '',
            todos: []
        }
        this.onChange = this.onChange.bind(this);
        this.addTodo = this.addTodo.bind(this);
        this.filterTodo = this.filterTodo.bind(this);
        this.toggleAll = this.toggleAll.bind(this);
        this.toggleTodo = this.toggleTodo.bind(this);
    }

    //getting text input value
    onChange = (e) => {
        this.setState({inputText: e.target.value})
    }

    // adding todo
    addTodo = (e) => {
        e.preventDefault();

        const newTodos = this.state.todos.concat([{text: this.state.inputText, id: Date.now(), completed: false}])
        this.setState({inputText: '', todos: newTodos},
            () => console.log(this.state.todos)
        )
    }

    // filtering todo
    filterTodo = (id) => {
        const filteredTodos = this.state.todos.filter((item) => item.id !== id);
        this.setState({todos: filteredTodos});
    }

    toggleAll = () => {
        const newTodos = this.state.todos;
        newTodos.forEach(todo =>
            todo.completed = !todo.completed
        )
        this.setState({todos: newTodos}, () => console.log(this.state.todos))
    }

    toggleTodo(i) {
        const newTodos = this.state.todos;
        newTodos[i].completed = !newTodos[i].completed
        this.setState({todos: newTodos});
    }

    // rendering view
    render() {
        return (
            <div>
                <Form
                    value={this.state.inputText}
                    onChange={this.onChange}
                    onSubmit={this.addTodo}
                />
                <button onClick={() => this.toggleTodo(1)}>Toggle All</button>
                <List
                    toggle={this.toggleTodo}
                    todos={this.state.todos}
                    onClick={this.filterTodo} 
                    />
            </div>
        );
    }
}

ReactDOM.render(<TodoApp />, document.getElementById('root'));
registerServiceWorker();

1 个答案:

答案 0 :(得分:2)

这应该适合你:

const List = (props) => (
    <div>
        {props.todos.map((todo, i) => <Todo key={todo.id} onClick={props.onClick} toggleTodo={() => props.toggle(i)} {...todo}/>)}
    </div>
)

一旦你这样做,你不需要使用Todo中的i,因为传入的函数已经特定于数组中的特定元素。

onClick={() => this.props.toggleTodo()}>

但是,我认为如果你使用了toggleTodo方法会更好,这样当你做这样的事情时它会起作用,但这需要某种查找:

onClick={() => this.props.toggleTodo(this.props.id)}

编辑:由于onClick事件位于li,因此删除工作已停止。一个简单的解决方法是:

<li className="todo">
  <span onClick={() => this.props.toggleTodo(i)}>
    <span className="btn-completed" style={{color: this.props.completed ? '#99cc99' : '#fafafa'}}>{'\u{2714}'}</span>
    <span style={{textDecoration: this.props.completed ? 'line-through' : 'none'}}>{this.props.text}</span>
  </span>
  <span className="btn-delete" onClick={() => this.props.onClick(this.props.id)} >{'\u{2716}'}</span>
</li>