Home > front end >  Updating Todo List in React Native Todo app using Redux & Redux Toolkit
Updating Todo List in React Native Todo app using Redux & Redux Toolkit

Time:01-12

I'm building an RN Todo App, which has 2 screens named as HomeScreen and EditScreen and it's look like this HomeScreen EditScreen.

But I don't know how to update from EditScreen using Redux. Please give me some solutions. I really appreciate it.

If you need more details to help me fix this problem, please let me know.

store.js

import {configureStore} from '@reduxjs/toolkit';
import taskSlice from './taskSlice';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {combineReducers} from 'redux';
import {persistReducer} from 'redux-persist';
import thunk from 'redux-thunk';

const reducers = combineReducers({
  tasks: taskSlice,
});
const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
  whitelist: ['tasks'],
};

const persistedReducer = persistReducer(persistConfig, reducers);

const store = configureStore({
  reducer: persistedReducer,
  devTools: process.env.NODE_ENV !== 'production',
  middleware: [thunk]
});

export default store;



taskSlice.js

import {createSlice, nanoid} from '@reduxjs/toolkit';
export const taskSlice = createSlice({
  name: 'tasks',
  initialState: [],
  reducers: {
    addTask: (state, action) => {
      console.log(nanoid());
      // 'dgPXxUz_6fWIQBD8XmiSy'

      console.log(action.payload);
      const newTask = {
        id: nanoid(),
        name: action.payload.task,
      };
      state.push(newTask);
    },
    deleteTask: (state, action) => {
      console.log('delete', action.payload.id);
      console.log('state', state);
      return state.filter(item => item.id !== action.payload.id);
    },
    editTask: (state, action) => {
      const index = state.findIndex(item => item.id === action.payload.id);
      const updatedState = [...state];
      return void(updatedState[index].name = action.payload.name);
    },
  },
});

export const {addTask, deleteTask, editTask} = taskSlice.actions;

export default taskSlice.reducer;

EditScreen.js

import React, {useState} from 'react';
import {
  View,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  Alert,
} from 'react-native';
import {useSelector} from 'react-redux';
import {editTask} from '../redux/taskSlice';
import {useDispatch} from 'react-redux';

const EditScreen = ({route, navigation}) => {
  const {item} = route.params; // get item from HomeScreen
  const todos = useSelector(state => state.tasks);
  console.log('todos', todos);
  const [value, setValue] = useState(item.name);
  const id = item.id;
  const dispatch = useDispatch();

  const update = () => {
    dispatch(editTask({id: id, name: value}));
  };

  const handleSubmit = (): void => {
    if (value.trim().length === 0) {
      Alert.alert('You need to enter a task');
      setValue('');
      return;
    }
  };

  return (
    <View style={{justifyContent: 'center', marginTop: 30}}>
      <Text style={styles.text}> Updating "{item.name}"</Text>

      <View>
        <TextInput
          style={styles.textInput}
          placeholderTextColor="pink"
          placeholder="New Todo..."
          value={value.toString()}
          onChangeText={text => setValue(text)}
        />
        <View style={styles.buttonStyle}>
          {/* Button */}
          <TouchableOpacity
            style={styles.button}
            onPress={() => {
              handleSubmit();
              update();
              navigation.pop(); //use this function to navigate back to the editing note
            }}>
            <Text style={{color: 'white'}}>Update</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.button}
            onPress={() => navigation.navigate('Home')}>
            <Text style={{color: 'white'}}>Cancel</Text>
          </TouchableOpacity>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  text: {
    fontSize: 24,
    color: 'red',
    marginLeft: 10,
  },
  textInput: {
    borderColor: 'black',
    borderWidth: 1,
    padding: 10,
    marginLeft: 20,
    width: '90%',
    borderRadius: 5,
    color: 'black',
  },
  button: {
    backgroundColor: 'black',
    padding: 10,
    margin: 10,
    width: '30%',
    borderRadius: 5,
    alignItems: 'center',
  },
  buttonStyle: {flexDirection: 'row', justifyContent: 'center'},
});

export default EditScreen;


*Update: My app works exactly what I want, I share my code if anyone has the same issue.

CodePudding user response:

you need to change a little bit in your redux setup have a look below

const taskSlice = createSlice({
  name: 'tasks',
  initialState: [],
  reducers: {
    addTask: (state, action) => {
      console.log(nanoid());
      // 'dgPXxUz_6fWIQBD8XmiSy'

      console.log(action.payload);
      const newTask = {
        id: nanoid(),
        name: action.payload.task,
      };
      state.push(newTask);
    },
    deleteTask: (state, action) => {
      console.log('delete', action.payload.id);
      console.log('state', state);
      return state.filter(item => item.id !== action.payload.id);
    },
    editTask: (state, action) => {
      const index = state.findIndex(item => item.id === action.payload.id);
      const updatedState = [...state];
      updatedState[index].name = action.payload.name;
    },
  },
});

export const {addTask, deleteTask,editTask} = taskSlice.actions;
export default taskSlice.reducer;

and from EditScreen.js update a task by sending taskid and task name that you have edited

import {useDispatch} from 'react-redux';
import {editTask} from '....path of taskSlice.js';
...

const dispatch = useDispatch();

const update = () => {
  dispatch(editTask({id:'<taskid>',name:'<editted_task_name>'}));

<TouchableOpacity
  style={styles.button}
  onPress={update}>
  <Text style={{color: 'white'}}>Update</Text>
</TouchableOpacity>
  • Related