Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从本地存储和URL哈希重新水合状态_Javascript_Reactjs_Url_Redux_Local Storage - Fatal编程技术网

Javascript 从本地存储和URL哈希重新水合状态

Javascript 从本地存储和URL哈希重新水合状态,javascript,reactjs,url,redux,local-storage,Javascript,Reactjs,Url,Redux,Local Storage,我已经写了下面的reducer,它是有效的,但它感觉我正在进入变异领域,可能有更好的方法来实现这一点。我有一个状态为reading的对象。可以从URL中的哈希以及读取对象中存储的名为OldReads的读取记录中提取读取。第三种方法是从本地存储中的持久状态中提取它。我希望URL提取的优先顺序,使共享更容易。这种方法行吗?如果不行,你能给我指出正确的方向吗 import { GENERATE_READING, GET_READING_FROM_HASH } from '../constants/ac

我已经写了下面的reducer,它是有效的,但它感觉我正在进入变异领域,可能有更好的方法来实现这一点。我有一个状态为reading的对象。可以从URL中的哈希以及读取对象中存储的名为OldReads的读取记录中提取读取。第三种方法是从本地存储中的持久状态中提取它。我希望URL提取的优先顺序,使共享更容易。这种方法行吗?如果不行,你能给我指出正确的方向吗

import { GENERATE_READING, GET_READING_FROM_HASH } from '../constants/actionTypes';
import { REHYDRATE } from 'redux-persist/constants';
import getHashFromUrl from '../utils/getHashFromUrl';
import getReadingFromHash from '../utils/getReadingFromHash';

// Check if URL has hash and set initial state to that reading.
const initialUrlHash = getHashFromUrl(window.location.pathname);
const initialUrlReading = initialUrlHash ? getReadingFromHash(initialUrlHash) : null;
const initialState = {
  arr: initialUrlReading ? initialUrlReading.arr : [],
  hash: initialUrlHash ? initialUrlHash : '',
  time: 0,
  oldReadings: []
};

export const reading = (state = initialState, action) => {
  switch (action.type) {
    case GENERATE_READING: {
      let reading = action.reading;
      // If old readings exists, save new reading to array of old readings.
      if (state.oldReadings) {
        reading.oldReadings = [ {
          hash: reading.hash,
          time: reading.time,
          amount: reading.arr.length
        }, ...state.oldReadings ];
        reading.oldReadings = reading.oldReadings.slice(0, 5);
      }
      // Otherwise create new array and save reading to it.
      else {
        reading.oldReadings = [{
          hash: reading.hash,
          time: reading.time,
          amount: reading.arr.length
        }];
      }

      return { ...state, ...reading };
    }

    case GET_READING_FROM_HASH:
      // Used when restoring reading for old hash.
      return { ...state, ...action.reading };

    case REHYDRATE: {
      const incoming = action.payload.reading;
      // If hydrating from local storage, check for hash in url and append
      // that reading on top of reading from local storage.
      if (incoming) {
        const urlHash = getHashFromUrl(window.location.pathname);
        if (urlHash && incoming.hash !== urlHash) {
          const urlReading = getReadingFromHash(urlHash);
          return { ...state, ...incoming, ...urlReading };
        } else {
          return { ...state, ...incoming };
        }
      } else {
      return state;
      }
    }

    default:
      return state;
  }
};

export default reading;

我认为您可以使用
Object.assign
来避免突变并简化代码。例如,与其让reading=action.reading,还不如让reading=action.reading
const reading=object.assign({},action.reading)
,后者仍然只是对原始对象的引用。这实质上是获取一个新的空对象,并将
action.reading
复制到其中。看看文档,
Object.assign
对于这类事情来说是非常宝贵的


说得好!我一定会解决的。我主要担心的是依赖于
窗口.位置的“不纯粹性”,而不仅仅是状态/动作。当然,这是有道理的。您可以使用
window.location.pathname
作为有效负载,从应用程序包装器的
组件didmount
发送一个操作,这样您就知道该窗口可用。这可能会让事情变得更干净。这听起来是一个非常好的主意,我们一定会研究这个!希望在补液操作之前发送,如果是这样,我可以添加一个类似于
hasSyncedFromUrl
的标志来检查
REHYDRATE
案例。