在React Native Todo应用中用Redux&Redux Toolkit实现待办项更新
React Native Todo应用Redux实现待办项更新方案
我正在开发一个React Native Todo应用,包含HomeScreen和EditScreen两个页面,但不知道如何在EditScreen中通过Redux实现待办项更新,恳请提供解决方案。以下是我的代码文件:
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;
问题修复方案
1. 修正taskSlice.js中的editTask reducer
原写法中return void(...)会返回undefined,导致Redux state被重置,利用Redux Toolkit内置的Immer可以直接修改state:
editTask: (state, action) => { const targetTask = state.find(item => item.id === action.payload.id); if (targetTask) { targetTask.name = action.payload.name; } },
2. 优化EditScreen的提交逻辑
原逻辑中输入为空时仍会执行更新和跳转,修改handleSubmit并调整按钮事件:
const handleSubmit = (): boolean => { if (value.trim().length === 0) { Alert.alert('You need to enter a task'); setValue(''); return false; } return true; };
按钮事件修改为:
onPress={() => { if (handleSubmit()) { update(); navigation.pop(); } }}
更新说明
我的应用已实现预期功能,分享代码供遇到相同问题的开发者参考。
内容的提问来源于stack exchange,提问作者Truong_hp
相关产品推荐
相关产品推荐

