业务层hooks怎么封装useSessionStorage

发布时间:2022-08-26 10:32:31 作者:iii
来源:亿速云 阅读:124

业务层hooks怎么封装useSessionStorage

在现代前端开发中,React Hooks 已经成为了一种非常流行的状态管理方式。Hooks 提供了一种更简洁、更灵活的方式来管理组件的状态和副作用。其中,useStateuseEffect 是最常用的 Hooks 之一。然而,在实际开发中,我们经常需要将状态持久化到浏览器的 sessionStorage 中,以便在页面刷新或重新加载时能够恢复之前的状态。本文将详细介绍如何在业务层封装一个 useSessionStorage Hook,以便在项目中更方便地使用 sessionStorage

1. 什么是 sessionStorage

sessionStorage 是浏览器提供的一种本地存储机制,它允许我们在浏览器会话期间存储数据。与 localStorage 不同,sessionStorage 中的数据只在当前会话期间有效,当用户关闭浏览器标签页或窗口时,数据将被清除。

sessionStorage 的主要特点包括:

2. 为什么需要封装 useSessionStorage

在实际开发中,我们经常需要将组件的状态持久化到 sessionStorage 中。例如,用户在表单中输入的数据、用户的偏好设置等。如果每次都需要手动操作 sessionStorage,代码会变得冗长且难以维护。因此,封装一个 useSessionStorage Hook 可以让我们更方便地管理 sessionStorage 中的数据。

封装 useSessionStorage 的好处包括:

3. 如何封装 useSessionStorage

接下来,我们将详细介绍如何封装一个 useSessionStorage Hook。我们将从基本的实现开始,逐步增加功能,最终实现一个功能完善的 useSessionStorage Hook。

3.1 基本实现

首先,我们来实现一个最基本的 useSessionStorage Hook。这个 Hook 将允许我们存储和读取 sessionStorage 中的数据。

import { useState, useEffect } from 'react';

function useSessionStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.sessionStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

export default useSessionStorage;

3.1.1 代码解析

3.1.2 使用示例

import React from 'react';
import useSessionStorage from './useSessionStorage';

function App() {
  const [name, setName] = useSessionStorage('name', 'John Doe');

  return (
    <div>
      <h1>Hello, {name}!</h1>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
    </div>
  );
}

export default App;

在这个示例中,我们使用 useSessionStorage 来存储用户的名字。当用户在输入框中输入名字时,名字会被存储到 sessionStorage 中。即使页面刷新,名字也会被保留。

3.2 处理复杂数据类型

在上面的实现中,我们假设 sessionStorage 中存储的是简单的数据类型(如字符串、数字、布尔值等)。然而,在实际开发中,我们可能需要存储更复杂的数据类型,如数组、对象等。为了处理这些复杂数据类型,我们需要对 useSessionStorage 进行一些改进。

3.2.1 改进代码

import { useState, useEffect } from 'react';

function useSessionStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.sessionStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    const handleStorageChange = (event) => {
      if (event.key === key) {
        setStoredValue(JSON.parse(event.newValue));
      }
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
    };
  }, [key]);

  return [storedValue, setValue];
}

export default useSessionStorage;

3.2.2 代码解析

3.2.3 使用示例

import React from 'react';
import useSessionStorage from './useSessionStorage';

function App() {
  const [todos, setTodos] = useSessionStorage('todos', []);

  const addTodo = () => {
    const newTodo = { id: Date.now(), text: 'New Todo' };
    setTodos([...todos, newTodo]);
  };

  return (
    <div>
      <h1>Todos</h1>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
      <button onClick={addTodo}>Add Todo</button>
    </div>
  );
}

export default App;

在这个示例中,我们使用 useSessionStorage 来存储一个待办事项列表。当用户点击“Add Todo”按钮时,一个新的待办事项会被添加到列表中,并存储到 sessionStorage 中。

3.3 处理过期时间

在某些情况下,我们可能希望 sessionStorage 中的数据在一定时间后自动过期。例如,用户的登录状态可能只需要在一段时间内有效。为了实现这个功能,我们可以对 useSessionStorage 进行进一步的改进。

3.3.1 改进代码

import { useState, useEffect } from 'react';

function useSessionStorage(key, initialValue, expirationMinutes) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.sessionStorage.getItem(key);
      if (item) {
        const { value, timestamp } = JSON.parse(item);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        return isExpired ? initialValue : value;
      }
      return initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      const item = {
        value: valueToStore,
        timestamp: Date.now(),
      };
      window.sessionStorage.setItem(key, JSON.stringify(item));
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    const handleStorageChange = (event) => {
      if (event.key === key) {
        const { value, timestamp } = JSON.parse(event.newValue);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        setStoredValue(isExpired ? initialValue : value);
      }
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
    };
  }, [key, expirationMinutes, initialValue]);

  return [storedValue, setValue];
}

export default useSessionStorage;

3.3.2 代码解析

3.3.3 使用示例

import React from 'react';
import useSessionStorage from './useSessionStorage';

function App() {
  const [token, setToken] = useSessionStorage('token', null, 5); // 5分钟后过期

  const login = () => {
    setToken('fake-token');
  };

  const logout = () => {
    setToken(null);
  };

  return (
    <div>
      <h1>Token: {token || 'No Token'}</h1>
      <button onClick={login}>Login</button>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

export default App;

在这个示例中,我们使用 useSessionStorage 来存储用户的登录令牌。令牌在5分钟后会自动过期。当用户点击“Login”按钮时,令牌会被存储到 sessionStorage 中;当用户点击“Logout”按钮时,令牌会被清除。

3.4 处理同步更新

在某些情况下,我们可能希望在多个组件之间共享 sessionStorage 中的数据,并且当一个组件更新数据时,其他组件也能及时响应。为了实现这个功能,我们可以使用 useEffect 来监听 sessionStorage 的变化,并在数据变化时更新组件的状态。

3.4.1 改进代码

import { useState, useEffect } from 'react';

function useSessionStorage(key, initialValue, expirationMinutes) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.sessionStorage.getItem(key);
      if (item) {
        const { value, timestamp } = JSON.parse(item);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        return isExpired ? initialValue : value;
      }
      return initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      const item = {
        value: valueToStore,
        timestamp: Date.now(),
      };
      window.sessionStorage.setItem(key, JSON.stringify(item));
      window.dispatchEvent(new Event('storage'));
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    const handleStorageChange = (event) => {
      if (event.key === key) {
        const { value, timestamp } = JSON.parse(event.newValue);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        setStoredValue(isExpired ? initialValue : value);
      }
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
    };
  }, [key, expirationMinutes, initialValue]);

  return [storedValue, setValue];
}

export default useSessionStorage;

3.4.2 代码解析

3.4.3 使用示例

import React from 'react';
import useSessionStorage from './useSessionStorage';

function ComponentA() {
  const [count, setCount] = useSessionStorage('count', 0);

  return (
    <div>
      <h1>Component A: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

function ComponentB() {
  const [count, setCount] = useSessionStorage('count', 0);

  return (
    <div>
      <h1>Component B: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

function App() {
  return (
    <div>
      <ComponentA />
      <ComponentB />
    </div>
  );
}

export default App;

在这个示例中,我们有两个组件 ComponentAComponentB,它们共享同一个 sessionStoragecount。当其中一个组件更新 count 时,另一个组件也会自动更新。

3.5 处理错误和边界情况

在实际开发中,我们可能会遇到一些错误和边界情况,例如 sessionStorage 不可用、存储空间不足等。为了确保 useSessionStorage 的健壮性,我们需要对这些情况进行处理。

3.5.1 改进代码

import { useState, useEffect } from 'react';

function useSessionStorage(key, initialValue, expirationMinutes) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      if (typeof window === 'undefined') {
        return initialValue;
      }

      const item = window.sessionStorage.getItem(key);
      if (item) {
        const { value, timestamp } = JSON.parse(item);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        return isExpired ? initialValue : value;
      }
      return initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      if (typeof window === 'undefined') {
        console.warn('sessionStorage is not available');
        return;
      }

      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      const item = {
        value: valueToStore,
        timestamp: Date.now(),
      };
      window.sessionStorage.setItem(key, JSON.stringify(item));
      window.dispatchEvent(new Event('storage'));
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }

    const handleStorageChange = (event) => {
      if (event.key === key) {
        const { value, timestamp } = JSON.parse(event.newValue);
        const isExpired = Date.now() - timestamp > expirationMinutes * 60 * 1000;
        setStoredValue(isExpired ? initialValue : value);
      }
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
    };
  }, [key, expirationMinutes, initialValue]);

  return [storedValue, setValue];
}

export default useSessionStorage;

3.5.2 代码解析

3.5.3 使用示例

import React from 'react';
import useSessionStorage from './useSessionStorage';

function App() {
  const [theme, setTheme] = useSessionStorage('theme', 'light');

  return (
    <div>
      <h1>Theme: {theme}</h1>
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        Toggle Theme
      </button>
    </div>
  );
}

export default App;

在这个示例中,我们使用 useSessionStorage 来存储用户选择的主题。如果 sessionStorage 不可用,代码仍然可以正常运行,并且不会报错。

4. 总结

通过本文的介绍,我们详细讲解了如何在业务层封装一个 useSessionStorage Hook。我们从基本的实现开始,逐步增加了处理复杂数据类型、过期时间、同步更新以及错误处理等功能。最终,我们实现了一个功能完善、健壮的 useSessionStorage Hook,可以在实际项目中方便地使用。

封装 useSessionStorage 不仅简化了代码,还提高了代码的可维护性和可读性。希望本文对你理解和应用 React Hooks 有所帮助。在实际开发中,你可以根据具体需求对 useSessionStorage 进行进一步的定制和扩展。

推荐阅读:
  1. javaweb业务层应该如何写
  2. react hooks的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

hooks

上一篇:微信小程序长按识别二维码的情况有哪些

下一篇:PHP怎么配合微信小程序实现获取手机号码

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》