Home > Back-end >  Why the state is not updating?
Why the state is not updating?

Time:08-15

I have created a state using react hook useState() at line 28 which is const [input, setInput] = useState('');. Then I updated the state by calling the setInput() at line 45 in the createTodo function at line 32. But when the function is executing, the state is not updating. There is no error on the console. I also added a console.log() after the state updating statement and the console.log() also executing but state is not updating.

My codes are given below.

App.jsx

import React, { useEffect, useState } from 'react';
import { AiOutlinePlus } from 'react-icons/ai';
import ToDo from './ToDo';
import { db } from './firebase';
import {
  addDoc,
  collection,
  deleteDoc,
  doc,
  onSnapshot,
  query,
  updateDoc,
} from 'firebase/firestore';

const style = {
  bg: `h-screen w-screen p-4 bg-gradient-to-r from-[#2F80ED] to-[#1CB5E0]`,
  container: `bg-slate-100 max-w-[500px] w-full m-auto rounded-md shadow-xl p-4`,
  heading: `text-3xl font-bold text-center text-gray-800 p-2`,
  form: `flex justify-between`,
  input: `border p-2 w-full text-xl`,
  button: `border p-4 ml-2 bg-purple-500 text-slate-100`,
  count: `text-center p-2`,
};

const App = () => {
  const [todos, setTodos] = useState([]);

  const [input, setInput] = useState('');  // this is the state

  // ************ firebase operations ************
  // create
  const createTodo = async event => {
    event.preventDefault();
    if (input === '') {
      alert('Please add some text');
      return;
    }

    // crating data to firebase
    await addDoc(collection(db, 'todos'), {
      text: input,
      completed: false,
    });

    setInput(''); // here state is not updating
  };

  // read
  useEffect(() => {
    const q = query(collection(db, 'todos'));
    const unsubscribe = onSnapshot(q, querySnapshot => {
      let todosArr = [];
      querySnapshot.forEach(doc => {
        todosArr.push({ ...doc.data(), id: doc.id });
      });
      setTodos(todosArr);
    });
    return () => unsubscribe();
  }, []);

  // update
  const toggleComplete = async todo => {
    await updateDoc(doc(db, 'todos', todo.id), {
      completed: !todo.completed,
    });
  };

  // delete
  const todoDelete = async id => {
    await deleteDoc(doc(db, 'todos', id));
  };

  return (
    <div className={style.bg}>
      <div className={style.container}>
        <h2 className={style.heading}>ToDo CRUD with Firebase</h2>
        <form onSubmit={createTodo} className={style.form}>
          <input
            type="text"
            className={style.input}
            placeholder="ToDo"
            onChange={event => setInput(event.target.value)}
          />
          <button className={style.button}>
            <AiOutlinePlus size={30} />
          </button>
        </form>
        <ul>
          {todos.map((todo, index) => (
            <ToDo
              key={index}
              todo={todo}
              toggleComplete={toggleComplete}
              todoDelete={todoDelete}
            />
          ))}
        </ul>
        {todos.length === 0 ? null : (
          <p className={style.count}>{`You have ${todos.length} todos`}</p>
        )}
      </div>
    </div>
  );
};

export default App;

Please have a look. How can I solve this problem?

CodePudding user response:

You are missing value={input} in your input element

   <input
       type="text"
       className={style.input}
       placeholder="ToDo"
       value={input}    <-- this
       onChange={event => setInput(event.target.value)}
    />

CodePudding user response:

<input
  type="text"
  className={style.input}
  placeholder="ToDo"
  **value={input}**
  onChange={event => setInput(event.target.value)}
/>

https://reactjs.org/docs/forms.html#:~:text=An input form element whose,called a “controlled component”.&text=Since the value attribute is,state the source of truth.

  • Related