在 React Native 中使用 React Hooks 的基本全局状态

Basic Global State with React Hooks in React Native

我一直在追赶 React Hooks 潮流,并决定一起推出 React Native 应用程序,尝试提供完整的 redux/global 状态实现。我一直在关注一些关于如何去做的文章,但我确实有一些问题。

我理解 useStateuseReducer 的概念,但我对事情的 Context 方面感到困惑。

第一个问题:在不使用 props 的情况下将状态对象向下传递到树的最佳方法是什么?这是我目前所知道的。通常,如果没有导航,您将有一个 DispatchContext 的子组件来接收道具。但是因为我确实有导航,所以我真的不想将状态传递到树下。我觉得这违背了 Context 和 hooks 的目的。我见过一些 value={dispatch}value={{somePieceOfState}} 的东西。如何将状态和调度都传递到组件树中?

import React, { useReducer } from 'react';
import Navigation from './Navigation';
import { DispatchContext } from './Context';
import { countReducer } from './reducers';

const App = () => {
  const [count, dispatchCount] = useReducer(countReducer, 0);

  const dispatch = action => [dispatchCount].forEach(fn => fn(action)); //provides one dispatch for the entire component tree

  const state = {
      count,
      //other pieces of state go here
  }

  return (
    <DispatchContext.Provider value={dispatch}>
      <Navigation />
      // <ChildComponent someStateProp={count} /> normal way to pass down props
    </DispatchContext.Provider>
  );
};

export default App;

第二个问题:做action和action creator最好的方法是什么?这个应该可以结合第一个问题来回答。这是附加到我的导航的组件。

import React, { useContext } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { DispatchContext } from './Context';
import { countUp, countDown } from './actions';

const Comp1 = () => {
  const dispatch = useContext(DispatchContext);
  return (
    <View>
      <TouchableOpacity
        onPress={() => dispatch(countUp)}
      >
        <Text>Up</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() => dispatch(countDown)}
      >
        <Text>Down</Text>
      </TouchableOpacity>
    </View>
  );
};

export default Comp1;

与之相关的操作:

import {
  COUNT_UP,
  COUNT_DOWN
} from './types';

export const countUp = () => {
  return {
    type: COUNT_UP
  };
};

export const countDown = () => {
  return {
    type: COUNT_DOWN
  };
};

和减速器:

import {
  COUNT_UP,
  COUNT_DOWN
} from '../actions/types';

export const countReducer = (state, action) => {
  console.log(action);
  switch (action) {
    case COUNT_UP:
      return state + 1;
    case COUNT_DOWN:
      return state - 1;
    default:
      return state;
  }
};

我知道操作和调度以及所有有效的方法,因为我 console.log() 在我的减速器中并且我得到了响应。但是当我 console.log(action) 时,它显示它是函数,动作本身而不是类型。如果我 console.log(action.type),它是未定义的。我在这里做错了什么?

最后一个问题:对于复杂的状态管理,这是一种合理的方法吗?我知道 useEffect() 和类似的东西,但是来自任何有过一些经验的人挂钩,它对 api 通话和位置跟踪以及诸如此类的东西有用吗?它是一种可扩展的方法吗?基本上我要问的是我不想深入研究这个问题并且必须将所有内容重构为基于 class 的组件,因为我不能用钩子做一些我需要用 [=51 做的事情=]是的。但我真的很喜欢这个 hooks 东西,我想坚持下去。继续前进好吗?

抱歉这么久了 post,但我觉得这些有答案的问题对其他希望使用 React Native 的人很有用。

您的错误是混淆了 action creatoraction。顾名思义,动作创建者在调用时创建动作。在您的情况下,您正在派遣一个动作创建者而不是派遣一个动作。您必须先调用函数。

<TouchableOpacity
  onPress={() => dispatch(countUp())}
>
// ...
<TouchableOpacity
  onPress={() => dispatch(countDown())}
>

在上述返工中,动作创建者在被传递给分派之前被调用()

你可以使用这个用 React Hooks 编写的小库来简化全局状态管理

yarn add @rawewhat/stora

那就这样用吧

import useStora from '@rawewhat/stora'

const [states, actions] = useStora()

states.yourState
actions.yourAction()

许多现有的 React 全局钩子库将 React 捆绑在其中,或对其进行修改。

此外,我不喜欢他们似乎都依赖 "strings" 作为键的方式,并且缺乏 TypeScript 强类型。

我只是想要一些简单的东西,没有可能会一直中断或泄漏内存的神奇东西。

所以我自己写了。检查来源 - 它非常简单:

https://www.npmjs.com/package/@fluffy-spoon/react-globalize

用法

首先,您需要为您的状态全局创建一个键,初始值可选。

//users.ts

import { createGlobal } from '@fluffy-spoon/react-globalize';

export const usersKey = createGlobal([{ firstName: "John", lastName: "Doe" }]);

然后,您可以简单地在您的组件之一中使用它,就像您使用 useState!

//index.ts

import { usersKey } from './users';

export const GlobalUserListComponent = () => {

    //users and setUsers behaves like useState, except they are now shared between all components!
    const [users, setUsers] = useGlobal(usersKey);

    ...
}