I am trying to save some data into DB whenever the state (using Redux) changes.
//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(<>
</>)
}
The only way I can call this function is by rendering it in index.js like
ReactDOM.render(
<React.StrictMode>
<CookiesProvider>
<Provider store={store}>
<Save/>
<App />
</Provider>
</CookiesProvider>
</React.StrictMode>,
document.getElementById('root')
);
Everything works fine and as expected but I want to know if this is the best approach. I tried searching for best practices for what I'm trying to achieve, but Im still unsure. My approach just seems 'off' and im not sure if there is a 'react-y' way of doing it or some better alternative. I appreciate any suggestions. Thank you!
CodePudding user response:
What you want is a custom hook, not a component. That would be the more "react-y" way to do it.
Custom hooks are functions that return objects, functions, or state, or nothing at all, but are allowed to use React hooks in them.
A refactor into a custom hook might look like this:
import { useEffect } from "react";
export const useSave = (destination) => {
useEffect(()=>{
console.log("destination has been edited")
//save into DB
}, [destination])
}
With this approach you would pass in destination
from your component that uses it. Call it just like a function at the top of your component and pass in arguments.
So for instance, in your 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 is looking for the use
keyword at the beginning of the function, that's how it knows it's a custom hook, and won't throw an error trying to use a React hook inside it.
Further
The return from the custom hook is very powerful, and can be used to return a function that dispatches to a reducer, or a valuable piece of state.
You would assign your hook to a variable and make use of it in your component.
Ex:
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 }
}
Then in your component:
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
}
</>
)
}
CodePudding user response:
I am trying to save some data into DB whenever the state (using Redux) changes.