如何在用户允许之前阻止 redux-persist 使用 LocalStorage?

Kar*_*ter 8 cookies local-storage reactjs redux redux-persist

在使用 LocalStorage 之前,我想通过单击横幅按钮来获得用户的同意。LocalStorage 通过redux-persist. 我正在使用redux和redux-persist如下:

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persitor} >
      <MyAppRouter />
    </PersistGate>
  </Provider>,
  document.getElementById("root")
)
Run Code Online (Sandbox Code Playgroud)

并store与persistor来自来了

import { createStore } from "redux"
import { persistStore, persistReducer } from "redux-persist"
import storage from "redux-persist/lib/storage"
import { rootReducer } from "../reducers/index"

const persistConfig = {
  key: "root",
  storage,
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

const store = createStore(persistedReducer)
const persistor = persistStore(store as any)
// `as any` is necessary as long as https://github.com/reduxjs/redux/issues/2709 is not fixed

export { store, persistor }
Run Code Online (Sandbox Code Playgroud)

redux-persist 创建对象后立即在 LocalStorage 中保持初始状态,这不是我想要的。

无论状态是否持久,我都想在我的 React 组件中使用 redux。

我认为减速器的细节无关紧要,因为它不会影响状态的存储位置/方式。

用户曾经表示同意使用 LocalStorage 和 cookie 的信息存储在 cookie 中。

只有在用户在第一次访问期间表示同意或 cookie 已经存在后,我怎么才能开始使用 LocalStorage 进行持久化?cookie 过期或已被删除的情况应包含在第一次访问的情况下。

为了尽量减少讨论,我正在寻找解决技术问题的解决方案。就法律要求而言,该请求可能是矫枉过正。

到目前为止我尝试过的事情:

  • 使用两个存储(可能是不好的做法),它们在一个App组件的状态下进行管理,Provider如示例所示。问题是一旦点击横幅按钮,页面就会重新呈现,这是不可接受的。
  • 评估黑名单将不起作用,因为它对状态的初始持久性没有影响。

[1] https://softwareengineering.stackexchange.com/questions/290566/is-localstorage-under-the-cookie-law

Shu*_*tri 5

这里的想法是 redux-persist 的持久化组件负责在 localStorage 中持久化数据或 redux 状态。

为了根据用户的同意做出决定,您需要有条件地呈现或不呈现PersistGate组件

要解决这样的问题,您可以在 Persistor 上编写一个自定义组件,它仅在授予权限时才呈现它。提示用户授予或拒绝权限的逻辑也可以放在同一个组件中

例子

class PermissionAndPersist extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        permission: this.getCookie('userLocalStoragePermission')
    }
  }

  getCookie(name) {
    //implement the getc ookie method using document.cookie or a library

    /* state returned must have the following syntax
         isPermissionGranted,
         isCookieExpired
    */ 

    // The above syntax can be determined based on whether cookie is present as well as by checking the expiry data if cookie was present
  }

  render() {
      const { permission } = this.state;
      const {children, persistor} = this.props;
      if(!permission.isPermissionGranted) {
         // no permission granted, return a plain div/Fragment
         return (
            <React.Fragment>
              {children}
            </React.Fragment>
         )
      }
      if(permission.isCookieExpired) {
          return <Modal>{/* here goes a component which asks for user permission and on click updates the state as well as update in cookie */}</Modal>
      }
      // now if the cookie is present and permission is granted and cookie is not expired you render the `PersistGate` component
      return <PersistGate persistor={persitor} >{children}</PersistGate> 
  }
}
Run Code Online (Sandbox Code Playgroud)

如上所述创建组件后,您将按如下方式渲染它

ReactDOM.render(
  <Provider store={store}>
    <PermissionAndPersist persistor={persitor} >
      <MyAppRouter />
    </PermissionAndPersist >
  </Provider>,
  document.getElementById("root")
)
Run Code Online (Sandbox Code Playgroud)

注意:您始终可以根据需求修改 PermissionAndPersist 组件的实现,但请注意,必须仅在所有条件都匹配时呈现 PeristGate。如果用户未授予权限,您也可能想清除 localStorage

编辑:由于要求实际上不是在单击用户横幅时重新呈现整个应用程序,因此我们需要进行一些更改。

首先,根据条件重新渲染 ModalComponent。其次,我们不能有条件地更改我们重新渲染的组件,否则整个应用程序都会刷新。到目前为止,实现它的唯一方法是实际实现逻辑以自己在 localStorage 中持久化 redux 状态并在刷新时最初获取它

class PermissionAndPersist extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        permission: this.getCookie('userLocalStoragePermission')
    }
  }

  getCookie(name) {
    //implement the getc ookie method using document.cookie or a library

    /* state returned must have the following syntax
         isPermissionGranted,
         isCookieExpired
    */ 

    // The above syntax can be determined based on whether cookie is present as well as by checking the expiry data if cookie was present
  }

  render() {
      const { permission } = this.state;
      const {children, persistor} = this.props;
      if(!permission.isPermissionGranted) {
         // no permission granted, return a plain div/Fragment
         return (
            <React.Fragment>
              {children}
            </React.Fragment>
         )
      }
      if(permission.isCookieExpired) {
          return <Modal>{/* here goes a component which asks for user permission and on click updates the state as well as update in cookie */}</Modal>
      }
      // now if the cookie is present and permission is granted and cookie is not expired you render the `PersistGate` component
      return <PersistGate persistor={persitor} >{children}</PersistGate> 
  }
}
Run Code Online (Sandbox Code Playgroud)

一旦你实现了上面的组件,你就需要监听PERSISTOR_HYDRATEreducer中的action并更新redux state。

注意:您可能需要添加更多处理来使持久和正确地重新水化,但想法保持不变