Cannot set boolean values in LocalStorage?
Asked Answered
D

12

180

I noticed that I cannot set boolean values in localStorage?

localStorage.setItem("item1", true);
alert(localStorage.getItem("item1") + " | " + (localStorage.getItem("item1") == true));

Always alerts true | false when I try to test localStorage.getItem("item1") == "true" it alerts true ... How can I set an item in localStorage to true?

Even if it's a string, I thought only === would check the type?

So

alert("true" == true); // should be true? 
Discretionary answered 16/7, 2010 at 8:33 Comment(0)
V
90

Firefox's implementation of Storage can only store strings, but on 2009 September, W3C modified the draft to accept any data. The implementation (still) isn't caught up yet (see Edit below).

So in your case the boolean is converted to a string.

As for why "true" != true, as written in the description of Equal (==) in MDC*:

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible.

Note that the string is converted to a Number instead of a Boolean. Since "true" converted to a number is NaN, it will not be equal to anything, so false is returned.

(*: For the actual standard, see ECMA-262 §11.9.3 “The Abstract Equality Comparison Algorithm”)


Edit: The setItem interface was reverted to accept strings only on the 2011 Sept 1st draft to match the behavior of existing implementations, as none of the vendors are interested in supporting storing non-strings. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 for detail.

Valuate answered 16/7, 2010 at 8:46 Comment(2)
If either operand is a number or a boolean, the operands are converted to numbers if possible - I totally didn't realize that. I thought if one were a string, the other was cast to a string. Cheers (+1).Vail
@Andy, check this useful notes on the subject.Scholarship
S
165

For the moment, all the implementations Safari, WebKit, Chrome, Firefox and IE, are following the current version of the WebStorage standard, where the value of the storage items can be only a string.

An option would be to use JSON parse and stringify method to serialize and deserialize the data, as I suggested some time ago in another question, for example:

var value = "true";
console.log(JSON.parse(value) === true); // true
Sterlingsterlitamak answered 16/7, 2010 at 8:41 Comment(4)
This will obviously break if the string passed in value is not valid JSON (for example JSON.parse("a random string"))Ecosystem
True @AdonisK. But if he is using JSON.stringify when setting all values then he is able to offload the responsibility of outputting valid JSON to the library. And that is a very stable library.Unaccountable
The current specification defines an interface where getItem only returns a string or null and setItem only accepts a string. Reading the other answer, it doesn’t seem this is going to change, so the wording in this answer is outdated.Pentachlorophenol
yeah — it's not an old version, it's the only version.Gamal
V
90

Firefox's implementation of Storage can only store strings, but on 2009 September, W3C modified the draft to accept any data. The implementation (still) isn't caught up yet (see Edit below).

So in your case the boolean is converted to a string.

As for why "true" != true, as written in the description of Equal (==) in MDC*:

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible.

Note that the string is converted to a Number instead of a Boolean. Since "true" converted to a number is NaN, it will not be equal to anything, so false is returned.

(*: For the actual standard, see ECMA-262 §11.9.3 “The Abstract Equality Comparison Algorithm”)


Edit: The setItem interface was reverted to accept strings only on the 2011 Sept 1st draft to match the behavior of existing implementations, as none of the vendors are interested in supporting storing non-strings. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 for detail.

Valuate answered 16/7, 2010 at 8:46 Comment(2)
If either operand is a number or a boolean, the operands are converted to numbers if possible - I totally didn't realize that. I thought if one were a string, the other was cast to a string. Cheers (+1).Vail
@Andy, check this useful notes on the subject.Scholarship
A
24

My solutions:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}
Arioso answered 2/5, 2016 at 8:46 Comment(4)
@koppor Maybe because if getItem would ever return a boolean, then this method will yield false results, since true == 'true' is false.Heliotherapy
..or plain localStorage.getItem(pre)==='true' without the restDisregard
@koppor why is this down-voted? because the self-righteous stackers are overflowing, literally :)Tubercle
"? true : false" is unnecessary since localStorage.getItem(pre) == 'true' already gives you a boolean resultYeasty
A
8

I'd like to point out that it might be kinda easier just to wrap plain boolean value inside object and then, using JSON.stringify create local storage content and other way around, JSON.parse to retrive it:

let storeMe = {
  myBool: true
}

localStorage.setItem('test', JSON.stringify(storeMe))
let result = JSON.parse(localStorage.getItem('test'))

Amyloid answered 18/2, 2021 at 8:18 Comment(0)
M
7

This is related to CMS’s answer.

Here’s a little function I’ve been using to handle the parsing part of this issue (the function will keep doing the Right Thing after the browser implementations catch up with the spec, so no need to remember to change out code later):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}
Multiped answered 16/7, 2010 at 9:9 Comment(1)
Isn't this unnecessary compared to JSON.parse? JSON.parse("true") and JSON.parse(true) already both return true, so will still do the right thing after browsers implement boolean localstorageHygienics
S
3

Use store.js:

localStorage.setItem('isUser', true)
localStorage.getItem('isUser') === "true" //true
npm i -D store

store.get('isUser')  //true
Spartan answered 8/4, 2017 at 23:34 Comment(1)
But is it really necessary to include a whole library just for this simple string-to-boolean conversion task?Baron
U
2

What I usually do is just save the value in LocalStore as a Boolean, and then retrieve with a parsing method, just to be sure for all browsers. My method below is customized for my business logic. Sometimes I might store smth as 'no' and still need false in return

function toBoolean(str) {
    if (typeof str === 'undefined' || str === null) {
        return false;
    } else if (typeof str === 'string') {           
        switch (str.toLowerCase()) {
        case 'false':
        case 'no':
        case '0':
        case "":
            return false;
        default:
            return true;
        }
    } else if (typeof str === 'number') {
        return str !== 0
    }
    else {return true;}
}
Uppish answered 2/10, 2017 at 10:29 Comment(0)
S
1

I'm not sure if LocalStorage can save boolean values but I can tell you that when you do alert("true" == true); it will never evaluate to true because you are implicitly comparing a string to a boolean. That is why to set boolean values you use true instead of "true".

Schmooze answered 16/7, 2010 at 8:39 Comment(3)
What about alert("1"==1)? Javascript is a strange (and inconsistent) beasty.Levant
@spender: that's because the right operand is cast to a string for the comparison. "1" === 1 would actually return false.Vail
@Kenny: whoops facepalm, thanks for the correction :-) I was mixed up because of how booleans cast to strings.Vail
O
1

eval can also be used carefully under some cases.

console.log(eval("true") === true) //true
Octagon answered 1/8, 2016 at 17:23 Comment(1)
Avoid eval since it can be unsafe. Prefer JSON.parse("true").Fissile
I
1

When I need to store a flag I usually do:
localStorage.f_active = true (stored value is 'true' and it's fine)
if localStorage.f_active — passes

and to unflag:
delete localStorage.f_active
if localStorage.f_active — doesn't pass (returned value is undefined)

Illusionism answered 15/5, 2022 at 10:44 Comment(0)
H
1

eval can also be used carefully under some cases.

localstorage.setItem("yourValue","true")

const yourValue = eval(
     localStorage.getItem("yourValue") as string
   );
 console.log(keepConnected) //true
 console.log(!keepConnected) //false
Handpick answered 15/1 at 17:33 Comment(0)
T
0

Since you cannot set a boolean value for a key in the local storage, this is what I do (the code is in TypeScript for clarity). Also, let's pretend that we're saving the Remember User option from some page (login or something else).

Set the key to a constant and export it, so you can utilize it in other components/files:

export const REMEMBER_USER_FLAG: string = 'remember_user';

Setter:

storeRememberUserData(rememberUser: boolean = false): void {
  localStorage.setItem(REMEMBER_USER_FLAG, JSON.stringify(String(rememberUser)));
}

And then the getter:

isRememberUserSet(): boolean {
  return JSON.parse(localStorage.getItem(REMEMBER_USER_FLAG)) === 'true';
}

Which will serve as a boolean and you can use as a flag.

Teresa answered 20/11, 2023 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.