It is difficult for me to understand this custom React hook. The code works, but I understand only some parts. It is a useLocalStorage hook. I will be grateful for any feedback.
This is my App.js file.
import "./App.css";
import useLocalStorage from "./useLocalStorage";
function App() {
const [name, setName] = useLocalStorage("NAME", "");
return (
<>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<div>My name is {name}</div>
</>
);
}
export default App;
This is my useLocalStorage.js file.
import { useEffect, useState } from "react";
function getSavedValue(key, initialValue) {
const savedValue = JSON.parse(localStorage.getItem(key));
if (savedValue) return savedValue;
return initialValue;
}
function useLocalStorage(key, initialValue) {
console.log(key);
console.log(initialValue);
const [value, setValue] = useState(() => {
return getSavedValue(key, initialValue);
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
});
return [value, setValue];
}
export default useLocalStorage;
I understand how the savedValue (in useLocalStorage.js) is passed to the App.js file. I just retrieve it with the getSavedValue function, like this.
const [value, setValue] = useState(() => {
return getSavedValue(key, initialValue);
});
And later, I pass it to the App.js with these two lines.
Firstly, I return the value in the useLocalStorage.js
return [value, setValue];
Secondly, I pass the value variable into the name variable in the App.js file.
const [name, setName] = useLocalStorage("NAME", "");
This is how the passing of the savedValue from useLocalStorage.js to App.js works. I think.
But how does it work the other way around? How is the updated name variable passed from App.js to useLocalStorage? It seems to me that only “NAME” and initialValue are passed from App.js to useLocalStorage.js. Like this.
const [name, setName] = useLocalStorage("NAME", "");
As a result, in the useLocalStorage.js, I am able to access the “NAME” and intitialValue(“”) with the console.log statement.
console.log(key);
console.log(initialValue);
And it works. But I do not have this option for the updated name variable. Or do I? How do I access the updated name variable (available in the App.js) in the useLocalStorage.js???
CodePudding user response:
To your first question ("How does the updated name variable get passed from App.js to useLocalStorage"):
The value returned by useLocalStorage
is the same as the useState
it uses internally. In other words,
your current setup is maintaining state in two places: in the useState
(internal to useLocalStorage
) and
in local storage itself.
To your second question ("Do I have access to the updated name variable"):
Yes. Your name
variable is value
.
While your code may have the intended effect, I don't think it works the way you think it does. Here's what will happen on the first render (assuming the key hasn't been set in localStorage yet):
- Your
App
component will calluseLocalStorage
with "NAME" and "" as parameters. - Your hook will call
useState
. It is passing a function that is only executed once (on first render). After that, this function is never called again. In this function, you callgetSavedValue
. This will try to get the key from local storage and return it if it exists. If not, it will return the initial value. - Finally, you return the
value
(which now is an empty string, theinitialValue
) and a setter. - Your App.js uses the
value
andsetValue
(which it callsname
andsetName
) to populate your form. - At some point in the future, your
useEffect
hook runs and saves the previously-returned initial value to local storage. Now, the key should be set
Now, you start typing in the input. Here's what will happen:
- The
setName
(which recall is actuallysetValue
) is called. This simply updates the internal state of the localStorage. - That update will cause a re-render of the
App
component. - Your
useLocalStorage
hook will get called again. This time, it won't call thegetSavedValue
function. It will return whatever was set when you calledsetName
/setValue
in step 1. - At some point in the future, your
useEffect
hook fires again inuseLocalStorage
, which will save the value to local storage.
In a nutshell, you are using localStorage as an out-of-band storage mechanism that is updated independently of the actual component state. If you refresh the page, it will initialize from the local storage (instead of using the initialValue
you pass in).
CodePudding user response:
How is the updated name variable passed from App.js to useLocalStorage?
The updated value is not passed in. That's managed internally, by useLocalStorage. It's the value
variable in const [value, setValue] = useState(//etc
But I do not have this option for the updated name variable. Or do I? How do I access the updated name variable (available in the App.js) in the useLocalStorage.js???
console.log(value);