2

我正在将 redux 用于动态网格的状态管理,其中有人可以添加自己的组件。我将这个库用于网格https://github.com/STRML/react-grid-layout

我想使用 Gun 作为持久层,用于将网格及其组件的当前状态存储和复制到用户配置文件中。我的应用程序目前不使用 Express.js,所以我在运行示例时遇到了一些问题,因为它们都使用 Express。我也在使用 react-gun 但我无法弄清楚如何使用 Redux Store Provider 设置 Gun Provider

是否有规范的方法/示例将 Gun 与 Redux 一起用于 React?

我试过这个

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import Gun from 'gun';
import { GunProvider } from 'react-gun';
import App from './App';
import configureStore from './redux/store/configureStore';
import * as serviceWorker from './serviceWorker';

const gun = Gun({ file: 'db' });

ReactDOM.render(
  <GunProvider gun={gun}>
    <Provider store={configureStore()}>
      <App />
    </Provider>
  </GunProvider>,
  document.getElementById('root')
);
serviceWorker.unregister();

和这个

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import Gun from 'gun';
import { GunProvider } from 'react-gun';
import App from './App';
import configureStore from './redux/store/configureStore';
import * as serviceWorker from './serviceWorker';

const gun = Gun({ file: 'db' });

ReactDOM.render(

  <Provider store={configureStore()}>
    <GunProvider gun={gun}>
      <App />
    </GunProvider>
  </Provider>,
  document.getElementById('root')
);
serviceWorker.unregister();

我没有看到任何构建或运行应用程序的错误

控制台日志开始

[HMR] Waiting for update signal from WDS...
gun.js:863 Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!

控制台日志显示我在上面的代码中记录的“数据”变量

data: Gun
_:
$: Gun {_: {…}}
ack: 1
back: {gun: Gun, $: Gun, opt: {…}, root: {…}, graph: {…}, …}
get: "data"
gun: Gun {_: {…}}
id: 79
on: ƒ onto(tag, arg, as)
put: undefined
root: {gun: Gun, $: Gun, opt: {…}, root: {…}, graph: {…}, …}
soul: "data"
tag: {in: {…}, out: {…}}
__proto__: Object
__proto__: Object

但我在 Chrome >> 应用程序选项卡 >> 本地存储中没有看到任何内容

我在日志中看到了这个,yarn build但我不确定它是否相关

WARNING in ../node_modules/gun/gun.js 10:16-28
Critical dependency: the request of a dependency is an expression
 @ ./index.jsx

这是我使用纱线构建/运行项目 package.json 的方式

  "scripts": {
    "start": "cross-env-shell NODE_ENV=development node --max-old-space-size=12288 node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode development --open",
    "build": "cross-env-shell NODE_ENV=production node --max_old_space_size=12288 node_modules/webpack/bin/webpack.js --mode production",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

这是我在组件中使用枪的方式

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { withGun } from 'react-gun';
import Logger from '../appLogger/logger';

const log = new Logger({
  childType: 'component',
  childName: 'Foo'
});


class Foo extends Component {
  static propTypes = {
    blah: PropTypes.string.isRequired
  };
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    const data = this.props.gun.get('data').once(() => {});
    log.debug({
      msg: '[component] [componentDidMount] MainLayout',
      methodType: 'componentDidMount',
      logObjectName: 'data',
      logObject: data
    });
  }

  render() {
    const { blah } = this.props;
    return (
      <div>
        {blah}
      </div>
    );
  }
}

export default withGun(Foo);

预期成绩 -

我应该会看到一个名为“gun”的条目 Chrome DevTools >> Application tab >> Local Storage

实际结果 -

我在 Chrome Chrome DevTools >> 应用程序选项卡 >> 本地存储中没有看到任何内容

4

1 回答 1

1

预先披露:我是一个竞争库的开发者,它还没有结束测试版(可能会被重命名):https ://github.com/rm-rf-etc/react-gun

您使用的react-gun库对我来说似乎毫无意义。通过删除它,您可以用更少的代码完成更多工作。

在您的项目中的某处,包括:

// ./setup-gun.js
import Gun from 'gun/gun';

const gun = Gun();
export default gun.get('app_root');

正如我们在 gitter 上讨论的那样,我建议将您的枪支数据直接绑定到反应组件,如下所示。但是如果你必须使用 redux,那就跳到 redux 的例子。

与枪反应

在你的组件内部,当数据进来时使用钩子触发更新。像这样:

// ./index.js

import React from 'react';
import node from './setup-gun.js';

export const Component = () => {
  const ref = React.useRef(null);
  const [count, setCount] = React.useState(0);
  ref.current = count;
  const increment = React.useCallback(() => setCount(ref.current + 1));

  React.useEffect(() => {
    node.get('count').on((val) => setCount(val));

    // you will also need to capture and store a reference to `chain.off`
    // inside of `.on` so you can call it when the component unmounts:
    // return () => listeners.forEach(l => l.off())
  }, []);

  return (
    <div>
      <button onClick={increment}>Increment</button>
      <div>{ref.current}</div>
    </div>
  );
};

如果您有多个状态数据要管理,则可以替换useStateuseReducer.

带 Redux 的枪

// ./gun-redux.js

import node from './setup-gun.js';
import { setCount } from './actions.js';

// export store after you configure it
import store from './store.js';

// trigger action from gun listener, will fire when count changes
node.get('count').on((val) => store.dispatch(setCount(val)));
// ./index.js

import React from 'react';
import node from './gun.js';

const countNode = node.get('count');
const increment = () => countNode.once((val) => countNode.put(val + 1));

const Component = ({ count }) => (
  <div>
    <button onClick={increment}>Increment</button>
    <div>{count}</div>
  </div>
);

const mapStateToProps = (state) => ({
  count: state.count,
});
export default connect(mapStateToProps)(Component);

我认为前一种方法(没有 redux)不会那么混乱。使用 gun 使 redux 变得毫无意义,因为您可以直接从 gun 读取当前状态并获取更新,因此使用 redux 会在您的框架中创建不必要的功能重复。

此示例假设您正在从 gun 中的应用程序根目录直接读取计数属性。显然,您会想要做更多类似的事情,您要绑定到的任何数据条目的字符串 IDconst countNode = node.get(recordId).get('count');在哪里。recordId

于 2019-08-18T02:20:57.197 回答