小编典典

在 React 应用程序中使用外部函数(例如不返回任何内容的组件)的最佳方式?

all

每当状态(使用 Redux)发生变化时,我都会尝试将一些数据保存到数据库中。

//Save.js
import { useSelector } from "react-redux";
import { useEffect } from "react";

export const Save = () => {
    const destination = useSelector((configureStore) =>
        configureStore.locations.destination
    )
    useEffect(()=>{
        console.log("destination has been edited")
        //save into DB
    }, [destination])
    return(<>  
    </>)
}

我可以调用这个函数的唯一方法是在 index.js 中渲染它

ReactDOM.render(
  <React.StrictMode>
    <CookiesProvider>

      <Provider store={store}>
        <Save/>
        <App />
      </Provider>

    </CookiesProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

一切正常,如预期的那样,但我想知道这是否是最好的方法。我尝试为我想要实现的目标寻找最佳实践,但我仍然不确定。我的方法似乎“关闭”,我不确定是否有“react-y”的方法或更好的选择。我很感激任何建议。谢谢!


阅读 79

收藏
2022-07-09

共1个答案

小编典典

你想要的是一个自定义钩子,而不是一个组件。那将是更“反应”的方式。

自定义钩子是返回对象、函数或状态或什么都不返回的函数,但允许在其中使用 React 钩子。

重构为自定义钩子可能如下所示:

import { useEffect } from "react";

export const useSave = (destination) => {

  useEffect(()=>{
    console.log("destination has been edited")
    //save into DB
  }, [destination])

}

destination使用这种方法,您将从使用它的组件传入。就像组件顶部的函数一样调用它并传入参数。

因此,例如,在您的App

import { useSelector } from "react-redux";
import useSave from "./filepath/useSave.js"

const App = () => {
  const destination = useSelector((configureStore) =>      
    configureStore.locations.destination
  )

  useSave(destination)

  return (<></>)
}

React 在函数的开头寻找use关键字,这就是它知道它是一个自定义钩子的方式,并且在尝试在其中使用 React 钩子时不会抛出错误。

更远

自定义钩子的返回非常强大,可以用来返回一个分派给reducer的函数,或者一个有价值的状态。

您可以将您的钩子分配给一个变量并在您的组件中使用它。

前任:

import { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { setSomeState } from "path/to/reducer.js"

export const useSave = (destination) => {
  const [saving, setSaving] = useState(false)

  const dispatch = useDispatch()

  useEffect(()=>{
    console.log("destination has been edited")
    setSaving(true)
    //save into DB
    setSaving(false)
  }, [destination])

  const updateStore = (state) => {
    dispatch(setSomeState(state))
  }

  return { saving, updateStore }
}

然后在您的组件中:

import { useSelector } from "react-redux";
import useSave from "./filepath/useSave.js"

const App = () => {
  const destination = useSelector((configureStore) =>      
    configureStore.locations.destination
  )

  const { saving, updateStore } = useSave(destination)

  return (
    <>
      {saving ? 
        <h1>Saving...</h1> 
        : 
        <button onClick={updateStore}>Set</button
      }
    </>
  )
}
2022-07-09