在自定义钩子中反应保留状态

时间:2021-03-02 21:38:59

标签: reactjs

从单独的组件调用自定义反应钩子时,有没有办法保留状态?我在这里做了一个简单的例子,但我想在我的应用程序中使用相同的逻辑来存储对 api 的 fetch 调用,并在我的应用程序的不同位置使用数据,而不会多次调用 api。

find . -print0 | xargs -0 sh -c 'for arg; do echo "Received: $arg"; done' _

在此示例中,import React, { useState, useEffect } from 'react'; function useCounter(intialCount = 0){ const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return [count, setCount]; } const AnotherComponent = () => { const [count] = useCounter(); return <div>{count}</div> } export default function App() { // Call custom hook `useCounter` to reuse Counter logic const [count, setCount] = useCounter(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> <button onClick={() => setCount(count - 1)}> Decrement </button> <AnotherComponent /> </div> ); } 是否可能与 AnotherComponent 具有相同的计数。出于性能原因,我不想在我的应用组件中使用上下文,因为我从 api 获得的数据是一个很大的列表。

3 个答案:

答案 0 :(得分:0)

是的,您可以通过设置 Context 来提供集中状态和自定义挂钩以模块化方式访问该状态,从而轻松实现您的目标。

假设我想与我的整个应用程序共享 foo

  • 创建上下文提供程序

FooContext.js

import { createContext, useState } from 'react'

export const FooContext = createContext()

const { Provider } = FooContext

export const FooProvider = ({ children }) =>{
    const [foo, setFoo] = useState('bar')

    return(
        <Provider value={{foo, setFoo}}>
            { children }
        </Provider>
    )
}
  • 现在用 foo 包装您的应用程序(或您想注意的部分 FooProvider
 <FooProvider>
    <RestOfApp/>
 </FooPrivider>
  • 现在只需创建一个自定义钩子即可轻松访问 foo 的值和 setter

useFoo.js

import { useContext } from 'react' 
import { FooContext } from './FooContext.js' 

export const useFoo = () =>{
    const { foo, setFoo } = useContext(FooContext)
    return [foo, setFoo]
}
  • 在组件中使用它(在 FooProvider 下)
import { useFoo } from './useFoo'

const ComponentWithFoo = () =>{
    const [foo, setFoo] = useFoo()

    const changeFoo = value => setFoo(value)

    return <p> { foo } </p>
}

请注意,除了钩子之外,您还可以使用 HOC 或渲染道具。

答案 1 :(得分:0)

如果你不想使用上下文,那么可以使用钩子之外的一些共享状态来实现你想要的:

let sharedCount = 0;

function useCounter(initialCount) {
  const [count, _setCount] = useState(sharedCount);

  // On first run, set initial count
  useEffect(() => {
    if (initialCount !== undefined) {
      sharedCount = initialCount;
    }
  }, []);

  // If shared count is changed by other hook instances, update internal count
  useEffect(() => {
    _setCount(sharedCount);
  }, [sharedCount]);

  const setCount = (value) => {
    sharedCount = value; // Update shared count for use by other hook instances
    _setCount(value);    // Update internal count
  };
  
  return [count, setCount];
}

答案 2 :(得分:0)

使用 SWRReact Query,它们会自动从服务器缓存您的数据并停止重复调用。