Почему мой последний оставшийся todo не удаляется при первом нажатии в React Redux

Я пытаюсь получить данные из firebase и отобразить их внутри компонента Todo, inputForm использует избыточную форму для обработки проверки. После отправки формы она вызывает создателя действий, который добавляет данные в базу данных firestore, а затем перечисляет элементы задач с помощью создателя действий listTodo, все эти запросы являются асинхронными и используют избыточный преобразователь в качестве промежуточного программного обеспечения, когда у меня есть список элементов задач. на экране, и я пытаюсь удалить последний элемент задачи, он не удаляется при первом нажатии, но мне нужно дважды щелкнуть, чтобы удалить элемент. Я не могу решить эту проблему, кто-нибудь помогите мне с этой проблемой.

App.js

class App extends React.Component {

    render() {
        return (
            <Container fluid>
                <h1 className="text-center" style={{marginTop: "5vh"}}>Todo App</h1>
                <InputForm/>
                <Todo />
            </Container>
        )
    }
}

export default App

InputForm.js

import React from 'react'
import { Button, Col, Container, Form, Row } from 'react-bootstrap'
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import {addTodo } from '../actions'



class InputForm extends React.Component {


    renderError = ({error, touched}) => {
        if(error && touched){
            return <p  style={{color: 'red'}}>{error}</p>
        }
    }

    todoInput = ({input, meta}) => {
         return (
             <Form.Group>
             <Form.Control  {...input} />
             {this.renderError(meta)}
             </Form.Group>
         );
     };

     todoDate = ({input, meta}) => {
        return (    
            <Form.Group>
                <Form.Control type="date" {...input} />
                {this.renderError(meta)}
            </Form.Group>
        );
    };

    handleSubmit = (inputValues) => {
        this.props.addTodo(inputValues);
        inputValues.todo_input = null;
        inputValues.todo_date = null;
    }
    render() {
        return (
            <Container fluid  style={{marginTop: "12vh", marginBottom: "2.5%"}}>
                <Form onSubmit={this.props.handleSubmit(this.handleSubmit)}> {/* just need to pass values to addtodo actions */}
                    <Row lg="auto" style={{marginLeft: "10%"}} >
                        <Col  md={6}>
                        <Field name="todo_input" component={this.todoInput} />
                        </Col><Col md="auto" >
                        <Field name="todo_date" component={this.todoDate} />
                        </Col><Col xs="auto" >
                            <Button type="submit" variant="success">Add Todo</Button>
                        </Col>
                    </Row>
                </Form>
            </Container>
        )
    }
}

const validate = (inputValue) => {
    const errors = {};
    //error.something, here something must match the value of name of a Field component
    if(!inputValue.todo_input){
        //only ran if title is empty
        errors.todo_input  = "Please enter the todo";
    }
    if(!inputValue.todo_date){
        errors.todo_date ="Please enter the deadline"
    }

    return errors;
   
}



export default connect(null, {addTodo})(reduxForm({
    form: 'todo-input',
    validate
})(InputForm));

Todo.js

import React from 'react'
import {  Col, ListGroup, Row } from 'react-bootstrap'
import DeleteIcon from '@material-ui/icons/Delete';
import {deleteTodo} from '../actions'
import {listTodo} from '../actions'
import {connect} from 'react-redux'


class Todo extends React.Component {

    componentDidMount(){
        this.props.listTodo();
    }
    
    render(){
       
        if(this.props.list.length === 0){
            return (
                <ListGroup.Item className="w-50 mx-auto my-2" variant="success" style={{}}>
               <Row>
                    <h5 className="mx-auto text-center">Enter the todo item</h5>
               </Row>
                <Row>
                <p className="mx-auto">Deadline date will be mentioned here</p>
                </Row>
           </ListGroup.Item>
            )
        }
        if(this.props.list)
             //<div>Hello</div>
             return this.props.list.map(todo => {
                //console.log(todo);
                return (
                    <ListGroup key={todo.id}>
                        <ListGroup.Item className="w-50 mx-auto my-2" variant="success">
                            <Row>
                                    <Col xs={1}>
                                    <DeleteIcon onClick={() => this.props.deleteTodo(todo.id)}/>
                                    </Col><Col md={10}>
                                    <h5 className="text-center">{todo.todo.todo}</h5>
                                    </Col>
                            </Row>
                                <Row>
                                <p className="mx-auto">Deadline by {todo.todo.date}</p>
                                </Row>
                        </ListGroup.Item>
                    </ListGroup>
                )
            })
    }
}

const mapStateToProps = (state) => {
     console.log(state.todoList);
     return  {
        list: state.todoList
    };
}

export default connect(mapStateToProps, {deleteTodo, listTodo})(Todo)

действия/index.js

   import database from '../firebase/firebase'
export const addTodo = (inputValue) => async dispatch => {
    await database.collection('Todo').add({
        todo: inputValue.todo_input,
        date: inputValue.todo_date
        });
        sendTodo(dispatch);
}

export const listTodo = () => async dispatch=> {
    //console.log("Hi")
    sendTodo(dispatch);
}

export const deleteTodo = id => async dispatch => {
    //delete todo
    database.collection('Todo').doc(id).delete();
    sendTodo(dispatch);
}

const sendTodo = async (dispatch) => {
    let data = [];
    let todoRef = database.collection('Todo');
    let allTodos =  await todoRef.orderBy('todo').get();
    for(const doc of allTodos.docs){
        data.push({
            id: doc.id,
            todo: doc.data()
        }) 
    }
    //console.log(data);
     dispatch ({
         type: 'LIST_TODO',
         payload: data
     });
}

редуктор.js

import { combineReducers } from "redux";
import {reducer as formReducer} from 'redux-form'
import todoReducer from './TodoReducer'

export default combineReducers({
    form: formReducer,
    todoList: todoReducer
});

Кроме того, иногда, даже если я не отправил форму, я получаю сообщение об ошибке на своем экране, может ли кто-нибудь помочь мне в этом!


person Chirag Lalwani    schedule 18.05.2021    source источник
comment
вы не обновляете todoList в функции deleteTodo, а также используете await с database.collection('Todo').doc(id).delete(), а затем обновляете список todoList   -  person Valeed Anjum    schedule 19.05.2021


Ответы (2)


Я подозреваю, что database.collection('Todo').doc(id).delete(), вероятно, сама по себе асинхронна. Не отправляйте обновленные задачи, пока они не обработаются. (Поместите на него .then и подождите, пока это произойдет).. или подождите.

person Atmas    schedule 18.05.2021

.delete() возвращает обещание. Используйте await внутри асинхронной функции.

export const deleteTodo = id => async dispatch => {
    //delete todo
    async database.collection('Todo').doc(id).delete();
    sendTodo(dispatch);
}
person Dharmaraj    schedule 19.05.2021