简体   繁体   中英

Store number using localStorage with custom hook React

I'm trying to store a number for a counter that initializes as 0 and counts up 1 every time a user uploads a photo. Im getting undefined in Profile console.log orderHook.orderCount. In localStorage i get console.log of {count:0}
Any help is greatly appreciated!

LocalStorage.js:

import { useState, useEffect } from 'react';

function getStorageValue(key, defaultValue) {
    // getting stored value
    const saved = localStorage.getItem(key);
    const initial = JSON.parse(saved); // unexpected character @ line 1 column 1 
    // const initial = JSON.stringify(saved); 
    return initial || defaultValue;
}

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

    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
    }, [key, value]);

    return [value, setValue];
};

Count.js: custom hook

import { useLocalStorage } from "../../Utilities/localStorage/localStorage"; // Local storage hook

function useOrderCountHook() {
    const [orderCount, setOrderCount] = useLocalStorage({count: 0}); // The profile image

    const changeOrderCount = () => {
        setOrderCount({ count: orderCount.count + 1 })
    }
    return { orderCount, changeOrderCount };
    // return [orderCount, changeOrderCount];
}

export default useOrderCountHook;

Profile.js: using customhook

    const orderHook = useOrderCountHook(); // How the photo count hook is called

    console.log(typeof (orderHook.orderCount)) // undefined
    console.log(orderHook.orderCount) // undefined

    const handleUploadChange = e => { // Input onChange 
        if (e.target.files[0]) {
            setImage(e.target.files[0]);
        } else { }
        return handleCountChange()
    };

    const handleCountChange = () => { // Function for custom count hook
        if (orderHook.orderCount === undefined) {
            return 
        } else {
            return orderHook.orderCount
        }
    }
      return (
                        {
                            currentUser ?
                                <input
                                    type="file"
                                    for="Upload Image"
                                    accept="image/*"
                                    name="image"
                                    id="file"
                                    onChange={handleUploadChange}
                                    onClick={handleUploadChange}
                                    style={{ display: "none" }}
                                />
                                : ''
                           }

                        <i className="bi bi-camera">      
                            {orderHook.orderCount === undefined ?
                                <span className="banner-list-font mx-1">0 photos</span>
                                :
                                <span className="banner-list-font mx-1">{orderHook.orderCount.count} photos</span>
                            }
                        </i>

**UPDATE**
So i managed to get it working but when i signed the user out and signed back in now if i try to upload a photo i get the error Cannot read properties of undefined (reading 'count'). which is the defaultValue prop and that console logs as undefined. I think the problem is that count is being stored as an object?

localStorage.js:

 import { useState, useEffect } from 'react'; // function getStorageValue(key, defaultValue) { // const saved = localStorage.getItem(key); // console.log(saved, defaultValue, key)// => null undefined {count:0} // const initial = JSON.parse(saved); // console.log(initial) // // const initial = JSON.stringify(saved); // // return key || defaultValue; // return initial || defaultValue; // } function getStorageValue(key, defaultValue) { const saved = localStorage.getItem(key); console.log(saved, defaultValue, key)// => null undefined {count:0} if (saved === null) { return defaultValue; } return JSON.parse(saved); } export const useLocalStorage = (key, defaultValue) => { console.log(key, defaultValue)// => {count:0} undefined const [value, setValue] = useState(() => { return getStorageValue(key, defaultValue); }); useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; };

Profile.js:
 return ( <input type="file" for="Upload Image" accept="image/*" name="image" id="file" onChange={e => { orderHook.changeOrderCount(e); handleUploadChange(e) }} onClick={handleUploadChange} style={{ display: "none" }} /> <i className="bi bi-camera"></i> {orderHook.orderCount === undefined || orderHook.orderCount === null? <span className="banner-list-font mx-1">0 photos</span>: <span className="banner-list-font mx-1">{orderHook.orderCount.count} photos</span> }

It looks like the error comes from your getStorageValue function, here is a fixed implementation:

function getStorageValue(key, defaultValue) {
  const saved = localStorage.getItem(key);
  if (saved === null) {
    return defaultValue;
  }
  return JSON.parse(saved);
}

I would recommend using a library instead of writing your own implementation of useLocalStorage . Check out the useStorage hook from the react-tidy library.

Disclaimer I am the author of that library.

Instead of:

    const [orderCount, setOrderCount] = useLocalStorage({count: 0}); // The profile image

you should use:

    const [orderCount, setOrderCount] = useLocalStorage("count", 0); // The profile image

Well i've been testing this for about 15 minutes and i cant get it to break so i think its working....then again i thought this feature was already working a week ago. Heres what i came up with.
LocalStorage.js:

import { useState, useEffect } from 'react';

function getStorageValue(key, defaultValue) {
    const saved = localStorage.getItem(key);
    console.log(saved, defaultValue, key)
    const initial = JSON.parse(saved); // unexpected character @ line 1 column 1 
    console.log(initial)
    if (initial === null || initial === undefined) {
        return key
    } else {
        return initial
    }
}

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

    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
    }, [key, value]);

    return [value, setValue];
};

Count.js:

import { useLocalStorage } from "../../Utilities/localStorage/localStorage"; // Local storage hook

function useOrderCountHook() {
    const [orderCount, setOrderCount] = useLocalStorage({count: 0}); // The profile image

    const changeOrderCount = () => {
        setOrderCount({ count: orderCount.count + 1 })
    }
    
    return { orderCount, changeOrderCount };
}

export default useOrderCountHook;

Profile.js:

const orderHook = useOrderCountHook(); // Photo count hook
                {
                    currentUser ?
                        <input
                            type="file"
                            for="Upload Image"
                            accept="image/*"
                            name="image"
                            id="file"
                            onChange={e => { orderHook.changeOrderCount(e); handleUploadChange(e) }}
                            onClick={handleUploadChange}
                            style={{ display: "none" }}
                        />
                        : ''
                }

                 <div className="">
                    <i className="bi bi-camera"></i>                              
                    {orderHook.orderCount === undefined || orderHook.orderCount === null ?
                    <span className="banner-list-font mx-1">0 photos</span> 
                     :
                     <span className="banner-list-font mx-1">{orderHook.orderCount.count} photos</span>                    
                  </div>

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