【问题标题】:Basic Global State with React Hooks in React NativeReact Native 中带有 React Hooks 的基本全局状态
【发布时间】:2019-10-15 16:34:18
【问题描述】:

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

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

第一个问题:在不使用道具的情况下将状态对象向下传递的最佳方法是什么?这是我目前所掌握的。通常,如果没有 Navigation,您将有一个 DispatchContext 的子组件来接收道具。但由于我确实有导航,我真的不想将状态传递给树。我觉得这违背了上下文和钩子的目的。我见过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;

第二个问题:做动作和动作创建者的最佳方式是什么?这大概可以结合第一个问题来回答。这是一个附加到我的导航的组件。

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 有好处吗电话和位置跟踪之类的东西?它是一种可扩展的方法吗?基本上我要问的是我不想深入研究这一点,并且必须将所有内容重构为基于类的组件,因为我不能用钩子做一些我需要用类做的事情。但我真的很喜欢这个钩子的东西,我想坚持下去。继续前进好吗?

抱歉,这篇文章很长,但我觉得这些有答案的问题对于那些希望通过 react native 陷入困境的其他人很有用。

【问题讨论】:

    标签: react-native redux state react-hooks react-context


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      yarn add @rawewhat/stora
      

      那就这样用吧

      import useStora from '@rawewhat/stora'
      
      const [states, actions] = useStora()
      
      states.yourState
      actions.yourAction()
      

      【讨论】:

        【解决方案3】:

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

        此外,我不喜欢他们似乎都依赖“字符串”作为键的方式,并且缺乏 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);
        
            ...
        }
        

        【讨论】:

          猜你喜欢
          • 2017-10-28
          • 2021-12-15
          • 1970-01-01
          • 1970-01-01
          • 2021-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-23
          相关资源
          最近更新 更多