【问题标题】:React Redux + redux persist : only part of the data persistsReact Redux + redux persist :只有部分数据持久化
【发布时间】:2017-02-06 13:01:59
【问题描述】:

这是一个使用 redux-persist 的 react-native 应用程序(redux-pattern),用于在用户没有互联网连接时持久保存数据。

问题是只有部分数据被持久化。请参阅下面的屏幕截图。 auth 被持久化并从AsyncStorage 加载,没有任何问题。但其他人coursesevaluations,...部分保留。 例如,课程/课程包含 1 的 userId,但它是一个空对象。

****更新新截图,登录后自动补水: Store.js:

import { persistStore, autoRehydrate } from "redux-persist";
import { applyMiddleware, createStore, compose } from "redux";
import { AsyncStorage } from "react-native";
import thunk from "redux-thunk";
import createLogger from "redux-logger";
import rootReducer from "./rootReducer";

const logger = createLogger();

const store = createStore(rootReducer, compose(
	applyMiddleware(thunk, logger),
	autoRehydrate()
));

persistStore(store, {storage: AsyncStorage});

export default store;

auth.reducer.js

import * as types from "./auth.actions";
export const INITIAL_STATE = {
	token: null,
	users: {}
};

export default function auth(state = INITIAL_STATE, action) {
	const {users, token} = state;
	switch (action.type) {
		case types.AUTH_LOGIN:
		users[action.payload.userId] = {
			token: action.payload.token,
			///.... continues
		};
		return Object.assign({}, state, {
			loading: false,
			token: action.payload.token,
			user: action.payload.userId,
			users: users
		});
		case types.AUTH_LOGIN_FAILED:
		return Object.assign({}, state, {
			users,
			token
		});
		case types.AUTH_LOGOUT:
		return Object.assign({}, state, {
			token: "",
			user: "",
			users: {}
		});
		default:
			return state;
	}
}

还有一些组件,例如查看课程代码:

courses.reducer.js

import * as types from "./courses.actions";

export const INITIAL_STATE = {
  courses: {}
};

export default function courses(state = INITIAL_STATE, action){
  const {courses, lectures, schedule, events, discussion} = state;
  switch(action.type){
    case types.GET_COURSES:
    return Object.assign({}, state, {
      courses: action.payload.courses,
      lectures: action.payload.lectures,
      schedule: action.payload.schedule,
      events: action.payload.events,
      discussion: action.payload.discussion
		});
    case types.GET_COURSES_FAILED:
    return state;
    case types.BOOK_COURSE:
    return state;
    case types.UNBOOK_COURSE:
    return state;
    case types.BOOK_COURSE_FAILED:
    return state;
    case types.UNBOOK_COURSE_FAILED:
    return state;
    default:
    return state;
  }
}

请问有什么解决办法吗?

*** 更新(由 petsome 请求) course.actions.js

export const GET_COURSES = 'GET_COURSES';
export const GET_COURSES_FAILED = 'GET_COURSES_FAILED';
export const BOOK_COURSE = 'BOOK_COURSE';
export const UNBOOK_COURSE = 'UNBOOK_COURSE';
export const BOOK_COURSE_FAILED = 'BOOK_COURSE_FAILED';
export const UNBOOK_COURSE_FAILED = 'UNBOOK_COURSE_FAILED';

import Functions from '../common/Functions';

export const getCourses = (users) => {
  return dispatch => {
    Functions.getCoursesAPI(users)
    .then((data)=>{
      const {courseList, lectureList, schedule, eventList, discussion, coursesArray} = data;
      return dispatch(coursesSuccess(courseList, lectureList, schedule, eventList, discussion, coursesArray));
      //return dispatch(coursesFailed('e'));
    })
    .catch((e)=>{
      return dispatch(coursesFailed(e));
    });
  };
};

export const bookCourse = (user, courseId, callback) => {
  return dispatch => {
    Functions.bookCourse(user, courseId, callback)
    .then((data)=>{
        return dispatch(bookCourseSuccess(data));
    })
    .catch((e)=>{
      return dispatch(bookCourseSuccessFailed(e));
    });
  };
};

export const unbookCourse = (user, courseId, callback) => {
  return dispatch => {
    Functions.unbookCourse(user, courseId, callback)
    .then((data)=>{
        return dispatch(unbookCourseSuccess(data));
    })
    .catch((e)=>{
      return dispatch(unbookCourseSuccessFailed(e));
    });
  };
};

const coursesSuccess = (courses, lectures, schedule, eventList, discussion, coursesArray) => {
  return {
    type: GET_COURSES,
    payload: {
      courses: courses,
      lectures: lectures,
      schedule: schedule,
      events: eventList,
      discussion: discussion,
      coursesArray: coursesArray
    }
  }
};

const coursesFailed = (e) => {
  return {
    type: GET_COURSES_FAILED,
    payload: {
      error: e
    }
  }
};

const unbookCourseSuccess = (data) => {
  return {
    type: UNBOOK_COURSE,
    payload: {
      data: data
    }
  };
};

const unbookCourseSuccessFailed = (e) => {
  return {
    type: UNBOOK_COURSE_FAILED,
    payload: {
      error: e
    }
  };
};

const bookCourseSuccess = (data) => {
  return {
    type: BOOK_COURSE,
    payload: {
      data: data
    }
  };
};

const bookCourseSuccessFailed = (e) => {
  return {
    type: BOOK_COURSE_FAILED,
    payload: {
      error: e
    }
  };
};

【问题讨论】:

  • 您需要包含问题的minimal, complete and verifiable example。总而言之:“最少——使用尽可能少的代码,但仍会产生同样的问题;完整——提供重现问题所需的所有部分;可验证——测试你将要提供的代码,以确保它重现问题”。
  • @AndrewWillems 大部分代码已被删除。谢谢。

标签: javascript reactjs react-native redux react-redux


【解决方案1】:

我不确定:

return Object.assign({}, state, {
            loading: false,
            token: action.payload.token,
            user: action.payload.userId,
            users: users
        });

成为最好的选择。

根据我的经验,要让你的减速器保持最新,你必须使用...state

case YOUR_NAME_CASE:
            return {
                ...state,
                //Your keys for update
            }

【讨论】:

  • 感谢您的回答。让我试试。我会在这里更新。
【解决方案2】:

根据我自己的经验,我建议您在 redux 存储中添加一个时间戳,以指示数据何时被持久化。这样当客户端尝试从服务器获取新数据时,它可以在更新 redux 存储之前从服务器请求时间戳以与客户端进行比较。同步客户端上的持久数据和来自服务器的数据可能不一致。

【讨论】:

  • 感谢您的回答,但我没有明白这一点。您的回答与问题有何关联?状态在更改后不会保持不变。
  • 每次操作后,nextState 都会被持久化。这就是 redux-persist 的目的。因此,如果您想保留某些部分,则可以使用库提供的白名单或黑名单选项。
  • 这实际上是我的问题。 nextState 没有被持久化!
  • 你能附加你的action creators来处理reducer中使用的action的调度吗?根据您的 redux 商店屏幕截图,您没有正确地将数据合并到商店。
  • 您的 redux-persist 操作何时分派?它应该在分派任何其他操作之前完成。如果在此之后完成,这可能会导致与 redux 存储中的数据不一致。如果有,请检查从 getCourses 异步操作返回的数据。您的 reducer 函数看起来不错,尽管您可以对其进行一些重构。
猜你喜欢
  • 2019-09-20
  • 2017-10-08
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
相关资源
最近更新 更多