React Native 从任何地方处理按钮onPress的最佳方式

fzwojiic  于 2022-12-19  发布在  React
关注(0)|答案(1)|浏览(198)

这个想法

我有一个屏幕,上面有一个"全局"按钮,底部有一些输入。默认情况下,这个"全局"按钮将转到"主页"屏幕。
我希望该按钮的工作方式如下:

  1. [input focused] -> [button changes to 'back'](当按钮处于"返回"状态时,按下时将模糊输入)
  2. [button clicked] -> [input blurred] -> [button changes back to 'home'].
    因此,我需要弄清楚如何在应用程序的任何组件中处理按钮的onPress
    (With输入我只用Keyboard.dismiss()就能做到,但这不仅仅是输入,我有一些组件,它们有自己的方式来按下按钮)
    我的方法
    我已经用contextapi做了这个,但是现在我不知道这是不是一个好主意...
    我有一个上下文提供程序,如下所示:
export default function MainButtonControlProvider({ children, goToHome }) {
  const [_type, setType] = useState('home');
  const [_onPressFn, setOnPressFn] = useState(() => goToHome);

  const reset = () => {
    setType('home');
    setOnPressFn(() => goToHome);
  }

  const set = ({ type, onPress }) => {
    setType(type);
    setOnPressFn(() => onPress);
  }

  return (
    <MainButtonControlContext.Provider value={{ _type, _onPressFn, reset, set }}>
      {children}
    </MainButtonControlContext.Provider>
  )
}

"全局"按钮如下所示:

export default function MainButton() {
  const { _type, _onPressFn } = useContext(MainButtonControlContext);

  const getIcon = () => {
    switch (_type) {
      case 'home':
        return <HomeIcon />
      case 'back':
        return <ChevronIcon size={32} rotation={-90} />
    }
  }

  return (
    <Button icon={getIcon()} onPress={_onPressFn} />
  )
}

输入如下:

export default function BasicInput() {
  const inputRef = useRef(null);
  const { set, reset } = useContext(MainButtonControlContext);

  return (
    <TextInput
      ref={inputRef}
      onFocus={() => set({ type: 'back', onPress: () => inputRef.current.blur() })
      onBlur={() => reset()}
    />
  )
}

问题是

因此,输入被聚焦,它改变了"全局"按钮的外观和onPress功能。
问题是,在执行set()reset()之后,树中也使用MainButtonControlContext-rerender中的set()reset()函数的其他组件...
他们这样做是很合乎逻辑的,因为状态被改变了,函数也在上下文提供者中被重新创建了......但是我该如何解决这个问题呢?
我本来可以在set()reset()函数上使用useCallback(),但是set()接受参数,并且它们总是不同的,所以这样做没有意义。
所以我需要一个不同的方法🥲
我从未使用过redux,但我认为学习它是一个好主意,所以如果有人有使用它的方法,我不介意为了性能而改变整个应用程序😅
我不明白的是如何处理按钮的onPress,因为redux状态需要是可序列化的...

    • 编辑:**

1.我试着用useState中的set替换上下文提供程序中的set()函数,并用useCallback Package reset(),成功了!不再需要重新呈现,但是在更换按钮时设置所有的 prop 是一件痛苦的事情(我现在有2个状态)。如果有人知道如何改变set函数从useState一点,而不触发rerenders,请帮助;)
1.我还尝试用useReducer替换所有的useState,但是由于某种原因,从useReducer更改state不会触发按钮的重新渲染...

qni6mghb

qni6mghb1#

使用Context API的方法不起作用。我通过将setreset函数 Package 在useCallback中修复了使用上下文的组件的重新呈现(我不知道我可以将参数传递给useCallback😅),但它什么也没做,因为提供程序中的所有组件在状态更改后仍然重新呈现...我甚至尝试记住状态,仍然不起作用。
我想我在使用API时遗漏了一些东西。如果有人知道如何处理提供者内部的状态,让我知道,这将是一个很好的教训;)

**我最终使用zustand来存储主按钮所需的状态。**Redux对于这样一个简单的应用程序来说感觉有点过头了,而且我也没有任何经验。

所以我只为主按钮创建了一个存储,如下所示:

import create from 'zustand';

export const useMainButtonStore = create((set, get) => ({
  type: 'home',
  onPress: () => console.warn('No onPress set in MainButttonStore.'),
  _default: null,

  set: (payload) => set(state => ({
    /* state from payload */
  })),
  reset: () => set(state => ({
    /* check if _default is set and then set state to _default */
  })),
  setDefault: (payload) => set(state => ({
    /* set _default on initial app render */
  })),
}))

然后是元件。这两个元件可以用shallow组合在一条线上。

const setMainButton = useMainButtonStore(state => state.set);
  const resetMainButton = useMainButtonStore(state => state.reset);

我担心的一个问题是是否可以存储函数。到目前为止,我在这方面没有问题。我确信在持久化这个存储时会有问题,因为函数是不可序列化的,但这样做是没有意义的:)

相关问题