【问题标题】:How to set React state from localStorage?如何从 localStorage 设置 React 状态?
【发布时间】:2018-04-03 00:49:45
【问题描述】:

我很难弄清楚如何使用 React 和 TS 从 localStorage 设置组件状态。在我检查 localStorage 实例是否存在后,它仍然说不兼容类型,因为localStorage.getItem() 仍然可以返回字符串或 null。

如果我更改界面并添加string | null,我可以从localStorage 设置状态,但是我不再能够自行设置localStorage,因为localStorage.setItem() 似乎只接受string 而不是string | null

编辑

我想出了这个问题的“解决方案”。我不确定这是否是不好的做法,但它似乎有效。如果这可以写得更好,请告诉我。

componentWillMount() {
    let from = localStorage.getItem('from');
    let to = localStorage.getItem('to');
    let fromId = localStorage.getItem('fromId');
    let toId = localStorage.getItem('toId');

    if (typeof from === 'string' &&
        typeof to === 'string' &&
        typeof fromId === 'string' &&
        typeof toId === 'string') {

      this.setState({
        inputFrom: from,
        inputTo: to,
        fromId: fromId,
        toId: toId,
      });
    }
  }

编译错误:

类型参数 '{ inputFrom: string |空值; }' 不可分配给“Pick”类型的参数。 属性“inputFrom”的类型不兼容。 键入'字符串 | null' 不可分配给类型 'string'。 类型 'null' 不能分配给类型 'string'。

我的接口实现如下:

interface State {
  inputFrom: string,
  inputTo: string,
  fromId: string,
  toId: string,
  tripdata: {},
  loading: boolean,
  error: boolean,
}

我的组件

import * as React from 'react';
import Header from './components/Header';
import SearchForm from './components/search/SearchForm';
import API from './api/APIService';
import TripTable from './components/trips/TripTable';
import Loading from './components/atoms/Loading';
import Error from './components/atoms/Error';
import './App.css';
const api = new API;

interface State {
  inputFrom: string,
  inputTo: string,
  fromId: string,
  toId: string,
  tripdata: {},
  loading: boolean,
  error: boolean,
}

class App extends React.Component<any, State> {
  constructor() {
    super();
    this.state = {
      inputFrom: '',
      inputTo: '',
      fromId: '',
      toId: '',
      tripdata: {},
      loading: false,
      error: false,
    };
  }

  componentWillMount() {
    let from = localStorage.getItem('from');
    if (from !== null || from !== undefined) {
      this.setState({
        inputFrom: from,
      });
    }
  }

  handleSubmit = () => {
      if (this.state.fromId !== '' && this.state.toId !== '') {
        this.setState({error: false});
        this.setState({loading: true});
        api.GetAccessToken()
        .then((token: string) => {
          api.GetTripFromSearch(token, this.state.fromId, this.state.toId)
        .then((res) => {
          this.setState({
            tripdata: res,
            loading: false,
          });
        });
          localStorage.setItem('from', this.state.inputFrom);
          localStorage.setItem('to', this.state.inputTo);
          localStorage.setItem('fromId', this.state.fromId);
          localStorage.setItem('toId', this.state.toId);
      });
    } else {
      this.setState({error: true});
    }
  }

  render() {
    let triptable: JSX.Element | null;
    let loading: JSX.Element | null;
    let error: JSX.Element | null;

    if (this.state.tripdata !== null) {
      triptable = <TripTable tripdata={this.state.tripdata} />;
    } else {
      triptable = null;
    }
    if (this.state.loading) {
      loading = <Loading />;
      triptable = null;
    } else {
      loading = null;
    }
    if (this.state.error) {
      error =  <Error />;
    } else {
      error = null;
    }
    return (
        <div>
          <Header />  
          <SearchForm 
            resetInputId={this.resetInputId}
            handleInputFrom={this.handleInputFrom}
            handleInputTo={this.handleInputTo}
            handleSubmit={this.handleSubmit}
            error={error}
            handleSwap={this.handleSwap}
          />
          {loading}
          {triptable}
        </div>        
    );
  }
}


export default App;

【问题讨论】:

标签: reactjs typescript local-storage


【解决方案1】:

在我的具体情况下,我试图从本地存储中获取布尔值。本地存储不保存布尔值。所以如果你给它'true',它会将它保存为一个字符串。这就是 if 的用途。实际上,您可以使这个看起来更漂亮,但为了清楚起见,我在这里使用了 else if。

在这种情况下,我将 checkLocalStorage 函数放置在组件之外。我不明白为什么它在组件内部不起作用,但 this 帖子告诉我将它放在组件外部,所以我就是这样做的。

ps:如果本地存储中没有任何内容,则为空。这是我用来设置默认值的。

const checkLocalStorage = () => {
  const ls = localStorage.getItem('item')
  if (ls === null || ls === 'true') {
    return true
  } else if (ls === 'false') {
    return false
  }
}

export const MyComponent = () => {

  const [state, setState] = useState(checkLocalStorage())

// rest of your code here

【讨论】:

  • 错字:第三行应该是if (ls === null || ls === 'true') {
  • @edemaine 正确。我庆祝得太早了,没有彻底测试它,哈哈。谢谢你的纠正。实际上有没有一种方法可以做到这一点而不必输入 ls === 两次?因为我找不到。
  • 不,这是最好的方法。您可以使用[null, 'true'].indexOf(ls) &gt;= 0,但这可能会慢一些。或者,您可以重组为 if (ls === 'false') return false else return true,它的行为略有不同(但更多的是布尔值)。
  • @edemaine Huh,老实说看起来很干净。我应该偷那个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 2019-08-16
  • 2017-06-26
  • 2018-09-16
相关资源
最近更新 更多