Home > Software engineering >  How to use input together with redux?
How to use input together with redux?

Time:12-12

I need your help. I'm trying to make a todo-app using redux. Now I try to render data from input by means of redux. I can't create and paint items when I click a button. Can you help me with this task, because I do not know how to use input with redux? In any case, here is a link to the project https://github.com/Dmytrii9Cherniak/inputs_redux Thank you

import React, {useState} from "react";
import {useDispatch, useSelector} from "react-redux";
import {ADD_TODO} from "../Redux/Action_Types";

export let Tasks = () => {

let tasks = useSelector(state => state.tasks);
const dispatch = useDispatch();
const [addTask, setNewTask] = useState('');
const handleInput = (e) => {
    setNewTask(e.target.value)
}
const handleButton = () => {
    dispatch({
        type: ADD_TODO,
        payload: {
            id: Date.now(),
            label: addTask
        }
    })
}
return (<div>
        <input
            value={addTask}
            onChange={handleInput}
        />
        <button onClick={handleButton}>Create Todo</button>

        {tasks.map(el => <div key={el.id}>{el.label}</div>)}

        </div>)
}

Todo_Reducer.js

import {ADD_TODO, DELETE_TODO} from "./Action_Types";

const initialState = {
allTasks : []
}

const todo_reducer = (state = initialState, action) => {
switch (action.type) {

case ADD_TODO: {
        return {
            ...state,
            allTasks: [...state.allTasks, action.payload]
        }
}

case DELETE_TODO: {
        return {
            ...state,
            allTasks: state.allTasks.filter(task => task.id !== action.payload)
        }
    }

default:
        return state;

   }
}

All_Reducers.js

import {combineReducers} from "redux";
import todo_reducer from "./Todo_Reducer";

export let root_reducer = combineReducers({
todo_reducer
})

Action_types.js

let ADD_TODO = 'ADD_TODO'
let DELETE_TODO = 'DELETE_TODO'

export {ADD_TODO, DELETE_TODO}

Store.js

import {createStore} from "redux";
import {root_reducer} from "./All_Reducers";

export let store = createStore(root_reducer)

CodePudding user response:

I checked your repo, the problem is here:

// All_Reducers.js
import { combineReducers } from 'redux';
import todo_reducer from './Todo_Reducer';

export let root_reducer = combineReducers({
  todo_reducer,
});

as above combineReducers, your state shape will be like this:

state = {todo_reducer: { allTasks: [] } }

so, to fix your problem, update your useSelector in the Tasks component like this:

let tasks = useSelector((state) => state.todo_reducer.allTasks);

CodePudding user response:

This code looks fine. Problem is with your redux action. Please share that code too. BTW, The re render only takes place when redux found new state different from previous state. Make sure you are not changing the content of previous state directly. Create a new copy of previous state and update the new one. Assuming, You have store like this :

{
  tasks : [{id: 1, label : "A"}]
}

What you can do is like this,

case "ADD_TODO" : 
const newTaskList = [store.tasks, action.payload] // [a, b, ...] will create a new copy of array with all items from a, b, ...
return {...store, tasks : newTaskList} // {a, b, ...} will create a new copy of object with all items from a, b, ...
  • Related