React.js使用相同的输入文本框编辑Todo项目

时间:2018-02-19 12:32:49

标签: javascript reactjs crud

我已经实现了简单的单页Todo应用程序,具有添加,编辑和删除功能。大部分部分已经完成,但我一度陷入困境。当我单击编辑按钮时,我想用顶部行的值填充顶部输入文本框,然后在编辑后我想在列表视图中更新。 你能指导我吗?

我创造了一个小提琴来解释它。

这是我的存储库: https://github.com/JigneshRaval/react-todo-app

JSFiddle网址:     https://jsfiddle.net/jigneshraval/3b3dabr6/20/

还可以通过点击"运行代码段"来粘贴下面的工作代码。按钮。



const Title = ({ todoCount }) => {
    return (
        <div>
            <div>
                <h1>Todos: ({todoCount})</h1>
            </div>
        </div>
    );
}

var randomString = function (length) {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}


class TodoForm extends React.Component {
    // Input Tracker
    constructor(props) {
        super(props);
        console.log(props.editTodo.title);
        this.state = { value: props.editTodo.title };
        this.input;
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({
            value: event.target.value
        })
    }

    handleSubmit(event) {
        event.preventDefault();
        console.log(event.target);
        let newTodoTitle = event.target.querySelector('input');
        this.props.addTodo(this.input.value);
        newTodoTitle.value = '';
    }

    renderAddTodoForm() {
        // Return JSX
        return (
            <form onSubmit={this.handleSubmit}>
                {/*<form onSubmit={(e) => {
                e.preventDefault();
                this.props.addTodo(this.input.value);
                this.input.value = '';
            }}>*/}
                <input className="form-control col-md-12 add-form"
                    ref={(input) => this.input = input}
                    value={this.state.value}
                    onChange={this.handleChange.bind(this)} />
                <br />
            </form>
        );
    }

    render() {
        return this.renderAddTodoForm();
    }
}


// 3. Single Todo
// ================================
const Todo = ({ todo, remove, edit }) => {
    // Each Todo
    return (
        <li className="list-group-item">
            <a href="#" data-todoid={todo._id} name="todoTitle" data-toggle="tooltip" data-placement="top" title="Click on item to delete.">{todo.title} =  {todo.status}</a>

            <button className="btn btn-danger float-right" onClick={() => { remove(todo._id) }}>Delete</button>
            <button className="btn btn-primary float-right" onClick={() => { edit(todo._id) }}>Edit</button>
        </li>);
}

// 2. Todo List
// ================================
const TodoList = ({ todos, remove, edit }) => {
    // Map through the todos
    const todoNode = todos.map((todo) => {
        return (<Todo todo={todo} key={todo._id} remove={remove} edit={edit} />)
    });

    return (<ul className="list-group" style={{ marginTop: '30px' }}>{todoNode}</ul>);
}

// 1. Main TODO App
// ================================
class TodoApp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [
                { "title": "Buy Milk", "status": "pending", "_id": "3QACIouhZZlhmm6T" },
                { "title": "Buy new computer book", "status": "pending", "_id": "9Xz2MSHIeh87WMgF" },
                { "title": "Fetch Money", "status": "pending", "_id": "DZvP2o5Dd4t9J3Ax" },
                { "title": "Play new game", "status": "pending", "_id": "Dp3J6BacTeG8ijV8" },
                { "title": "new 2", "status": "pending", "_id": "ECDUmbjOt4vtOKSv" },
                { "title": "sdfsdafsaf", "status": "pending", "_id": "GwHBilbjsbXipQuI" },
                { "title": "New 10", "status": "pending", "_id": "HGWGsNEVFNXIGZ8S" },
                { "title": "ppp", "status": "pending", "_id": "IExYBTFUFkGoHqyN" }
            ],
            isEditing: false,
            editTodo: {}
        }
    }

    // Add Todo
    addTodo(value) {
        this.state.data.push({ "title": value, "status": "pending", "today": { "$$date": Date.now() }, "_id": randomString(16) });
        this.setState({ data: this.state.data });
    }

    // Edit Todo
    editTodo(todoId) {
        const remainder = this.state.data.filter((todo) => {
            if (todo._id === todoId) return todo;
        });
        this.setState({ isEditing: true, editTodo: remainder[0] });
    }

    // Remove Todo
    removeTodo(id) {
        // Filter all todos except the one to be removed
        const remainder = this.state.data.filter((todo) => {
            if (todo._id !== id) return todo;
        });
        this.setState({ data: remainder });
    }


    handleInputChange(newValue) {
        console.log(newValue);
    }

    render() {
        return (
            <main>
                <div className="container">
                    <Title todoCount={this.state.data.length} />
                    <TodoForm isEditing={this.state.isEditing} handleInputChange={this.handleInputChange.bind()} editTodo={this.state.editTodo} addTodo={this.addTodo.bind(this)} />
                    <TodoList
                        todos={this.state.data}
                        remove={this.removeTodo.bind(this)}
                        edit={this.editTodo.bind(this)}
                    />
                </div>
            </main>
        )
    }
}

ReactDOM.render(
    <TodoApp />,
    document.getElementById('app')
);
&#13;
<script src="https://unpkg.com/react@16.2.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.2.0/umd/react-dom.development.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />

<div id="app"></div>
&#13;
&#13;
&#13;

有谁可以请指导我。

2 个答案:

答案 0 :(得分:0)

我会将所有内容分成两部分:TodoApp和Todo。

TodoApp有一个表单和一个包含所有子信息的数组。

Todo有其功能和信息显示。

然后使用正常模式,如答案:How to update parent's state in React?

我希望这会有所帮助。

答案 1 :(得分:0)

您需要在ToDoForm组件中添加如下生命周期钩子,如下所示。但是为setState添加条件,以便仅当next与this.state.value

不同时才调用它
componentWillReceiveProps (next) {
   this.setState({value: next.editTodo.title});
}

这将填充表单中的文本。您可以在此行之后进行进一步更改。

请参阅我们应该使用componentWillReceiveProps而不是componentWillUpdate来设置state