A
A
aleks_web_dev2020-05-23 14:42:25
React
aleks_web_dev, 2020-05-23 14:42:25

Reducer is called 2 times in useReducer?

I have a simple todo application.
The problem is: the reducer is called 2 times. Each todo item has a checkbox, when you click on it, the checked value changes to the opposite, but due to the fact that this happens 2 times, it remains the same as it was. Everything worked fine before useReducer .
Tried to call dispatch.bind(null,action) didn't help, replaced onChange with onClick didn't work
. Action 'add' and 'del' work, they are also called 2 times but everything is displayed correctly in the DOM.
Seravno I can't understand why the reducer is called 2 times.

Doki read the video, watched it, copied the counter from the offsite. There, too, the reducer was called op 2 times
. I use only useReducer , without redux

App.js

import React, { useState, useEffect, useReducer } from "react";
import TodoList from "./TodoList";

export const ContextApp = React.createContext();

const reducer =(state,action)=>{
  console.log('reducer')
  switch (action.type) {
    case 'add':
      console.log('add')
        return [
          ...state,
          {
            id: new Date()+Math.random(),
            title: action.title,
            desc: action.text,
            checked: false,
          }
        ]
    case 'checked':
      return state.map(item=>{
          if(item.id === action.id){
            item.checked = !item.checked;
          }
          return item;
        })
    case 'del':
      return state.filter(item=>item.id!==action.id)
    default:
      return state
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, [])

  const [todoValue, setValue] = useState({
    input: "",
    text: "",
  });
  useEffect(()=>{
    console.log(state);
  },[state])

  return (
    <ContextApp.Provider value={{dispatch}}>
      <div className="App">
        <div className="create_box">
          <input
            type="text"
            id="input"
            onChange={({ target }) => {
              setValue({
                [target.id]: target.value,
                text: todoValue.text,
              });
            }}
          />
          <textarea
            id="text"
            onChange={({ target }) => {
              setValue({
                input: todoValue.input,
                [target.id]: target.value,
              });
            }}
          ></textarea>
          <button onClick={()=>dispatch({
            type:'add',
            title:todoValue.input,
            text:todoValue.text
            })}> add </button>
        </div>
        <div className="todo_list" >
          <TodoList todo={state} />
        </div>
      </div>
    </ContextApp.Provider>
  );
}

export default App;


TodoItem.js // checkbox here
import React, { useContext } from 'react';
import { ContextApp } from './App';

const TodoItem = ({title,desc,checked,id}) => {
    const {dispatch} = useContext(ContextApp)
    return (
        <div className={!checked?"todo_item":"todo_item check"}>
            <h2>{title}</h2>
            <p className="desc">{desc} </p>
            <input type="checkBox" checked={checked} onChange={()=>{dispatch({
                type:'checked',
                id
            })}} />
            <button onClick={()=>{
                dispatch({
                    type:'del',
                    id
                })
            }}>del</button>
        </div>
    );
}
 
export default TodoItem;


import React from 'react'
import TodoItem from './TodoItem'

export default function TodoList({todo}) {
    return todo.map(item=> <TodoItem key={item.id} {...item} />)
};


There is already a similar question on the site, I asked it, but there was no correct answer

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
paoluccio, 2020-05-23
@aleks_web_dev

switch (action.type) {
  // ...
  case 'checked':
    return state.map(item => {
      if (item.id === action.id) {
        return { ...item, checked: !item.checked };
      }
      return item;
    });
  // ...
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question