【问题标题】:New React Context API + LocalStorage + Subscribe (Replacement for Redux)新的 React Context API + LocalStorage + Subscribe(替代 Redux)
【发布时间】:2019-01-11 08:01:49
【问题描述】:

我有一个使用 Redux 的应用程序。 Is 存储全局状态,如下图:

创建商店:

import {createStore, applyMiddleware} from 'redux';
import rootReducer from '../reducers';
import thunk from 'redux-thunk';

const configureStore = initialState => {
  return createStore(
    rootReducer,
    initialState,
    applyMiddleware(thunk)
  );
};

export default configureStore;

处理本地存储

  const storageName = 'xxxState';
  export const loadState = () => {
  try {
    const serializedState = localStorage.getItem(storageName);
    if (serializedState === null) {
      return undefined;
    }
    return JSON.parse(serializedState);
  } catch(err) {
    return undefined;
  }
};

export const saveState = state => {
  try {
    const serializedState = JSON.stringify(state);
    localStorage.setItem(storageName, serializedState);
  } catch(err) {
    throw err;
  }
};

最后启动应用会话:

import React from 'react';
import ReactDOM from 'react-dom';
import Start from './start';
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';
import { loadState, saveState } from './store/localStorage';
import throttle from 'lodash/throttle';

const persistedState = loadState();

const store = configureStore(persistedState);
store.subscribe(throttle(() => {
  saveState(store.getState());
}, 1000));

ReactDOM.render(
  <Provider store={store}>
    <Start />
  </Provider>,
  document.getElementById('root'));

完美运行。所以我的问题是:有没有可能对新的 React Context API 做同样的事情?

使用新的上下文我很舒服,我只想了解 store、localstorage 和 subscribe。因此,即使用户离开应用程序,状态也会保持不变。

【问题讨论】:

    标签: reactjs redux local-storage state react-context


    【解决方案1】:

    store.js

    import React, { Component, createContext } from "react";
    
    export const createStore = store => {
      const Context = createContext();
      let self;
      const setState = (action, state, args) => {
        self.setState(state);
      };
      const actions = Object.keys(store.actions).reduce(
        (accumulator, currentValue) => {
          return {
            ...accumulator,
            [currentValue]: function(...args) {
              let result = store.actions[currentValue](
                { state: self.state, actions: self.value.actions },
                ...args
              );
              if (result) {
                result.then
                  ? result.then(result => setState(currentValue, result, args))
                  : setState(currentValue, result, args);
              }
            }
          };
        },
        {}
      );
      class Provider extends Component {
        constructor() {
          super();
          this.state = store.initialState;
          self = this;
          this.value = {
            actions,
            state: this.state
          };
        }
        render() {
          if (this.state !== this.value.state) {
            this.value = {
              actions,
              state: this.state
            };
          }
          return (
            <Context.Provider value={this.value}>
              {this.props.children}
            </Context.Provider>
          );
        }
      }
      class Consumer extends Component {
        renderProps = ({ actions, state }) => {
          // const { mapStateToProps, mapDispatchToProps } = this.props;
          return this.props.children({
            state: state,
            actions: actions
          });
        };
        render() {
          return <Context.Consumer>{this.renderProps}</Context.Consumer>;
        }
      }
      const connect = (mapStateToProps, mapDispatchToProps) => WrappedComponent => {
        return (
          <Consumer
            mapStateToProps={mapStateToProps}
            mapDispatchToProps={mapDispatchToProps}
          >
            {injectedProps => (
              <WrappedComponent {...injectedProps} {...this.props} />
            )}
          </Consumer>
        );
      };
      return {
        Provider,
        Consumer,
        connect
      };
    };
    

    然后对于单个页面,您可以像这样进行操作和初始存储值

    import { createStore } from "@src/store";
    import { Actions } from "../actions";
    import { storage } from "@helpers/storage";
    import constants from "@src/constants";
    
    import { util } from "@src/utils";
    
    function getInitialState() {
      let Id = null;
      if (storage.get(constants.STORAGE_KEY)) {
        let storageObject = storage.get(constants.STORAGE_KEY);
        Id = storageObject["Id"];
        selectedDate = storageObject["selectedDate"];
      }
      return {
        data: null,
        activeTab: "score",
        Id: Id
      };
    }
    const store = {
      initialState: getInitialState(),
      actions: Actions
    };
    
    export const { Provider, Consumer } = createStore(store);
    

    终于在你的页面/HomePage/index.js 你可以有 从 './store' 导入 { Provider };

    render() {
      return (
        <Provider>
         <Homepage user={user} children={children} />
        </Provider>
      );
    }
    

    在你的页面/HomePage/Homepage.js 你可以有

    render() {
          return (
            <Consumer>
              {({ state, actions }) => {
                return this.renderChildrens(state, actions);
              }}
            </Consumer>
          );
        }
      }
    

    【讨论】:

      【解决方案2】:

      首要任务

      • Redux 具体与react 无关,它是一个状态管理器。
        它可以帮助您管理一个包含应用程序状态的大型 JavaScript 对象。

      • react 的 Context API 甚至不是 React 中的一个新特性,它一直都在那里,只是换了一张新面孔。这是一种将数据传递给没有prop drilling 的孩子的方法。

      我认为您指的是react-redux
      react-redux 是一种抽象,一种绑定您的 Redux 存储以做出反应的方法。 它正在为您完成所有商店订阅,并帮助您创建 Container 和使用 connect HOC 和 Provider 组件的消费者。
      它还有助于传递存储对象(通过底层的上下文 API)。

      如果您已经在使用Redux,我认为不使用react-redux 没有任何意义。

      您可以阅读更多关于差异的详细信息In this post(完全公开,我是作者)。

      【讨论】:

        猜你喜欢
        • 2020-09-22
        • 2019-05-29
        • 1970-01-01
        • 2016-12-10
        • 2021-07-11
        • 2020-03-29
        • 1970-01-01
        • 1970-01-01
        • 2020-04-27
        相关资源
        最近更新 更多