简体   繁体   中英

React custom hook setValue is undefined when used inside another component

I've a useLocalStorage hook. If I use it directly in my component, when I try to update the value I get an error setValue is not a function. It's actually undefined.

This is the code snippet

// https://github.com/Ibaslogic/localstorage-react-hook-project/blob/main/src/useLocalStorage.js
import { useState, useEffect } from "react";

function getStorageValue(key, defaultValue) {
  // getting stored value
  if (typeof window !== "undefined") {
    const saved = localStorage.getItem(key)
    const initial = saved !== null ? JSON.parse(saved) : defaultValue
    return initial;
  }
}

export const useLocalStorage = (key, defaultValue) => {
  const [value, setValue] = useState(() => {
    return getStorageValue(key, defaultValue)
  })

  useEffect(() => {
    // storing input name
    localStorage.setItem(key, JSON.stringify(value))
  }, [key, value])

  return [value, setValue]
}

export default useLocalStorage

And this is my component I wanna use this hook in:

import useLocalStorage from '../hooks/useLocalStorage'

const MyComponent = () => {  
  const [val, setVal] = useLocalStorage('test', '')
  ..

  useEffect(() => {
    setVal('thats a test')
    ..
  })

This component also has a Context (through useContext). If I use the useLocalStorage hook inside the context, and importing it to MyComponent - the code works:

// context/MyProvider.js
import { createContext } from "react";
import useLocalStorage from '../hooks/useLocalStorage'

const MyContext = createContext({})

export const MyProvider = ({ children }) => {
  const [value, setValue] = useLocalStorage("test", null)
  ..

  return (
    <MyContext.Provider value={{ value, setValue }}>
      {children}
    </MyContext.Provider>
  )
}

export default AuthContext

// components/MyComponent.js
import { useContext } from "react"; 
import MyContext from "../context/MyProvider";

const MyComponent = () => {  
  const { value, setValue } = useContext(MyContext)
  ..

  useEffect(() => {
    setValue('thats a test')
    ..
  })

Can someone please explain this? Why can't a I use the custom hook with my component?

I did a codesandbox and the issue was with saved being undefined. You can change the useLocalStorage hook to this and it worked for me:

function getStorageValue(key, defaultValue) {
  // getting stored value
  if (typeof window !== "undefined") {
    const saved = localStorage.getItem(key);
    const initial =
      saved !== null && saved !== "undefined"
        ? JSON.parse(saved)
        : defaultValue;
    return initial;
  }
}

You need to have your <MyComponent/> inside your <MyProvider><MyComponent/></MyProvider> to be able to call consume it's context

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM