【问题标题】:Can't set state after saving it to local storage in React将状态保存到 React 中的本地存储后无法设置状态
【发布时间】:2018-11-17 04:28:00
【问题描述】:

我正在我的应用中实现搜索过滤器,并且需要在浏览器刷新之间保留数据。

这是我的代码:

    class App extends Component {
  state = {
    data: shop,
    direction: {
      price: "asc",
      title: "asc"
    },
    searchTitle: "",
    searchPrice: {
      min: null,
      max: null
    }
  };

  componentDidUpdate() {
    const state = {
      searchTitle: this.state.searchTitle,
      searchPrice: this.state.searchPrice,
      direction: this.state.direction
    };

    window.localStorage.setItem("saved_state", JSON.stringify(state));
  }

  componentDidMount() {
    const state = JSON.parse(window.localStorage.getItem("saved_state"));

    console.log(state);

    if (state) {
      this.setState({
        searchTitle: state.searchTitle,
        searchPrice: state.searchPrice,
        direction: state.direction
      });
    }
  }

  // PRICE SORT
  priceSort = key => {
    this.setState({
      data: shop.sort(
        this.state.direction[key] === "asc"
          ? (a, b) => parseFloat(a.data[key]) - parseFloat(b.data[key])
          : (a, b) => parseFloat(b.data[key]) - parseFloat(a.data[key])
      ),
      direction: {
        [key]: this.state.direction[key] === "asc" ? "desc" : "asc"
      }
    });
  };

  // OLD PRICE SORT
  oldPriceSort = key => {
    this.setState({
      data: shop.sort(
        this.state.direction[key] === "asc"
          ? (a, b) => parseFloat(a.data[key]) - parseFloat(b.data[key])
          : (a, b) => parseFloat(b.data[key]) - parseFloat(a.data[key])
      ),
      direction: {
        [key]: this.state.direction[key] === "asc" ? "desc" : "asc"
      }
    });
  };

  // TITLE SORT
  titleSort = key => {
    this.setState({
      data: shop.sort(
        this.state.direction[key] === "asc"
          ? (a, b) => a.data[key].localeCompare(b.data[key])
          : (a, b) => b.data[key].localeCompare(a.data[key])
      ),
      direction: {
        [key]: this.state.direction[key] === "asc" ? "desc" : "asc"
      }
    });
  };

  // TITLE FILTER
  updateTitleSearch = event => {
    this.setState({
      searchTitle: event.target.value
    });
    this.titleSearch();
  };

  titleSearch = () => {
    if (this.state.searchTitle) {
      this.setState({
        data: shop
          .filter(item => {
            return (
              item.data.title
                .toLowerCase()
                .indexOf(this.state.searchTitle.toLowerCase()) !== -1
            );
          })
          .sort(
            this.state.direction.title === "asc"
              ? (a, b) => a.data.title.localeCompare(b.data.title)
              : (a, b) => b.data.title.localeCompare(a.data.title)
          )
      });
    }
  };

  // PRICE FILTER
  updateMinSearchPrice = event => {
    this.setState({
      searchPrice: { ...this.state.searchPrice, min: event.target.value }
    });
  };

  updateMaxSearchPrice = event => {
    this.setState({
      searchPrice: { ...this.state.searchPrice, max: event.target.value }
    });
  };

  priceSearch = () => {
    if (this.state.searchPrice.min || this.state.searchPrice.max) {
      this.setState({
        data: shop
          .filter(item => {
            return (
              parseFloat(item.data.price) >= this.state.searchPrice.min &&
              parseFloat(item.data.price) <= this.state.searchPrice.max
            );
          })
          .sort(
            this.state.direction.price === "asc"
              ? (a, b) => parseFloat(a.data.price) - parseFloat(b.data.price)
              : (a, b) => parseFloat(b.data.price) - parseFloat(a.data.price)
          )
      });
    }

    if (!this.state.searchPrice.max) {
      this.setState({
        data: shop.filter(item => {
          return parseFloat(item.data.price) >= this.state.searchPrice.min;
        })
      });
    }
  };

  render() {
    return (
      <div className="page-container">
        <h1>Welcome to ShopMeNow!</h1>
        <Filters
          updateTitleSearch={this.updateTitleSearch}
          titleSearch={this.titleSearch}
          updateMinSearchPrice={this.updateMinSearchPrice}
          updateMaxSearchPrice={this.updateMaxSearchPrice}
          priceSearch={this.priceSearch}
        />
        <ItemTable
          data={this.state.data}
          priceSort={this.priceSort}
          oldPriceSort={this.oldPriceSort}
          titleSort={this.titleSort}
        />
      </div>
    );
  }
}

export default App;

我的目标是在 componentDidMount() 挂钩中获取保存的数据。但它似乎不起作用(我已经尝试过 console.log 它)

我必须做些什么才能让它继续下去?感谢社区!

【问题讨论】:

  • “似乎不起作用”是什么意思?
  • 我的意思是它不起作用。
  • 能否包含整个组件,以便我们查看您如何更新状态等?
  • 刚刚更新了代码。
  • 很抱歉,只是回复说“它不起作用”对我们没有任何帮助。它没有按预期更新您的组件?您是否收到回溯错误?

标签: javascript reactjs local-storage


【解决方案1】:

与其在 ComponentDidMount 中设置 State ,不如创建一个完全不同的函数,然后在 ComponentDidMount 中调用该函数。

所有设置状态代码都添加到该功能中。 试试这个,让我知道它是否有效,干杯!

    ComponentDidMount(){ 

       this.changeValues();

   }

   changeValues(){

     const state = JSON.parse(window.localStorage.getItem("saved_state"));

    console.log(state);

    if (state) {
      this.setState({
        searchTitle: state.searchTitle,
        searchPrice: state.searchPrice,
        direction: state.direction
      });
    }

   }

【讨论】:

  • 嗨!不,它不起作用。但是,console.log 显示 localStorage 运行良好,并且所有内容都保存到我的状态。到底是怎么回事?
  • 您没有构造函数,也没有使用绑定 this。.bind(this) - 检查此示例 [link] (codepen.io/gaearon/pen/xEmzGg?editors=0010),它可能会有所帮助。
  • 我使用的是相同的箭头函数。这不是问题所在。 console.log 消息告诉我状态发生了变化。但不知何故,过滤器不起作用。
【解决方案2】:

我认为的问题是您将数据保存在 componentDidUpdate 内的 localStorage 中,并且您试图从 componentDidMount 中的本地存储中获取数据。

您需要了解 componentDidMount 在 componentDidUpdate 之前调用,这意味着您在设置之前正在从本地存储中读取数据。

所以需要先设置数据,再读取数据

【讨论】:

  • 你的意思是我应该交换componentDidMount和componentDidUpdate的代码吗?我试过了,但应用程序崩溃了。
  • 它是有道理的...猜猜我会沿着你提供的道路前进...将在这里报告结果。谢谢我的男人!
【解决方案3】:

您在 componentDidUpdate 中这样做有什么特别的原因吗?如果没有,我建议将该功能移至单独的功能。现在的情况,任何更新,包括 data 上的 this.setStates,您不想保存到 localStorage。

也许您可能会考虑编写一个设置状态并保存到 localStorage 的函数,因为您的排序函数已经相当庞大了。

示例伪代码:

setStateWithLocalStorage = newState => {
  const { searchTitle, searchPrice, direction } = this.state;
  this.setState(newState, () => {
      localStorage.setItem('saved_state', { searchTitle, searchPrice, direction })
  })
}

那么你可以在你的排序函数上使用这个函数而不是this.setState

【讨论】:

  • 哇!非常感谢。会检查并报告结果。
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 2017-06-11
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
相关资源
最近更新 更多