Persisting React State in LocalStorage

栏目: IT技术 · 发布时间: 5年前

内容简介:Let's say we're building a calendar app, like Google Calendar. The app lets you toggle between three different displays: month, week, and day.Personally, I always want to see the "Week" view. It gives me everything I need to know about the current day, whi

Let's say we're building a calendar app, like Google Calendar. The app lets you toggle between three different displays: month, week, and day.

Toggling between views in a typical calendar application

Personally, I always want to see the "Week" view. It gives me everything I need to know about the current day, while also giving me a peek at what's coming up in the next couple of days.

Thankfully, calendar apps know that users have strong preferences around this kind of thing, and the toggle is “sticky” . If I switch from “week” to “month” and refresh the page, the “month” view is the new default; it sticks.

Conversely, it's super annoying when form controls aren't sticky. For example: every month, I create 4-5 expenses through Expensify. Every single time, I have to swap the default currency from USD to CAD. Why can't it remember that I'm Canadian??

In this tutorial we'll see how we can create a custom React hook to abstract away the "stickiness", so we get it for free whenever we need it.

Here's what our custom hook looks like:

js
function useStickyState(defaultValue, key) {
  const [value, setValue] = React.useState(() => {
    const stickyValue = window.localStorage.getItem(key);

    return stickyValue !== null
      ? JSON.parse(stickyValue)
      : defaultValue;
  });

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

  return [value, setValue];
}

function useStickyState ( defaultValue , key ) {

const [ value , setValue ] = React . useState ( ( ) => {

const stickyValue = window . localStorage . getItem ( key ) ;

return stickyValue !== null

? JSON . parse ( stickyValue )

: defaultValue ;

} ) ;

React . useEffect ( ( ) => {

window . localStorage . setItem ( key , JSON . stringify ( value ) ) ;

} , [ key , value ] ) ;

return [ value , setValue ] ;

}

To show how it works, here's a quick counter demo with a sticky count. Try clicking it a few times, and then refresh this page:

If this code isn't clear to you, fear not! The rest of this tutorial explains it in greater detail :dizzy:

This hook makes a single assumption, which is reasonably safe in React apps: the value powering a form input is held in React state.

Here's a non-sticky implementation of a form control to switch between values:

jsx
const CalendarView = () => {
  const [mode, setMode] = React.useState('day');

  return (
    <>
      <select onChange={ev => setMode(ev.target.value)}>
        <option value="day">Day</option>
        <option value="week">Week</option>
        <option value="month">Month</option>
      </select>

      {/* Calendar stuff here */}
    </>
  )
}

const CalendarView = ( ) => {

const [ mode , setMode ] = React . useState ( 'day' ) ;

return (

< >

< select onChange = { ev => setMode ( ev . target . value ) } >

< option value = " day " > Day </ option >

< option value = " week " > Week </ option >

< option value = " month " > Month </ option >

</ select >

{ /* Calendar stuff here */ }

</ >

}

We can use our new "sticky" variant by swapping out the hook:

js
const CalendarView = () => {
  const [mode, setMode] = useStickyState('day', 'calendar-view');

  // Everything else unchanged
}

const CalendarView = ( ) => {

const [ mode , setMode ] = useStickyState ( 'day' , 'calendar-view' ) ;

// Everything else unchanged

}

While the useState hook only takes 1 argument—the initial value—our useStickyState hook takes two arguments. The second argument is the key that will be used to get and set the value persisted in localStorage. The label you give it has to be unique, but it otherwise doesn't matter what it is.

Fundamentally, this hook is a wrapper around useState . It just does some other stuff too.

First, it takes advantage of lazy initialization lazy initialization . This lets us pass a function to useState instead of a value, and that function will only be executed the first time the component renders, when the state is created.

js
const [value, setValue] = React.useState(() => {
  const stickyValue =
    window.localStorage.getItem(key);

  return stickyValue !== null
    ? JSON.parse(stickyValue)
    : defaultValue;
});

const [ value , setValue ] = React . useState ( ( ) => {

const stickyValue =

window . localStorage . getItem ( key ) ;

return stickyValue !== null

? JSON . parse ( stickyValue )

: defaultValue ;

} ) ;

In our case, we're using it to check for the value in localStorage. If the value exists, we'll use that as our initial value. Otherwise, we'll use the default value passed to the hook ("day", in our earlier example).

The final step to this is to make sure that we update localStorage whenever the state value changes. For that, our trusty friend useEffect comes in handy:

js
React.useEffect(() => {
  window.localStorage.setItem(name, JSON.stringify(value));
}, [name, value]);

React . useEffect ( ( ) => {

window . localStorage . setItem ( name , JSON . stringify ( value ) ) ;

} , [ name , value ] ) ;

This hook is a small but powerful example of how custom hooks let us invent our own APIs for things. While packages packages exist exist that solve this problem for us, I think there's a lot of value in seeing how to solve these problems ourselves ‍♂️

Special thanks to Satyajit Sahoo for a couple refactor suggestions :stars:

Last Updated: February 24, 2020


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入理解计算机系统(原书第3版)

深入理解计算机系统(原书第3版)

Randal E.Bryant、David O'Hallaron / 龚奕利、贺莲 / 机械工业出版社 / 2016-11 / 139.00元

和第2版相比,本版内容上*大的变化是,从以IA32和x86-64为基础转变为完全以x86-64为基础。主要更新如下: 基于x86-64,大量地重写代码,首次介绍对处理浮点数据的程序的机器级支持。 处理器体系结构修改为支持64位字和操作的设计。 引入更多的功能单元和更复杂的控制逻辑,使基于程序数据流表示的程序性能模型预测更加可靠。 扩充关于用GOT和PLT创建与位置无关代码的......一起来看看 《深入理解计算机系统(原书第3版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具