【问题标题】:How to recover state on back button with react如何通过反应恢复后退按钮的状态
【发布时间】:2016-02-12 16:45:42
【问题描述】:

如果我有一个简单的反应组件,它记录一个按钮的点击次数,并且每次点击都会记录一个新的历史状态而不更改 URL。当用户点击返回时,我如何将状态恢复到原来的状态?

我可以使用本机 JavaScript 历史记录对象,但当用户转换回第一个状态并从不同组件返回到此组件的最后一个状态时,它会失败。

我怀疑使用 react-router (1.0) 可以更好地做到这一点?

import React, { Component } from 'react';

export default class Foo extends Component {
  state = {
    clickCount: 0,
  };

  componentWillMount() {
    window.onpopstate = (event) => {
      if (event.state.clickCount) {
        this.setState({ clickCount: event.state.clickCount });
      }
    };
  }

  onClick() {
    const newClickCount = this.state.clickCount + 1;
    const newState = { clickCount: newClickCount };
    this.setState(newState);
    history.pushState(newState, '');
  }

  render() {

    return (
      <div>
        <button onClick={this.onClick.bind(this)}>Click me</button>
        <div>Clicked {this.state.clickCount} times</div>
      </div>
    );
  }
}

【问题讨论】:

  • 在 react-router 中检查浏览器历史记录。
  • 也许this answer 帮助。
  • 您可以将 localStorage 用于您的状态。为什么不呢?

标签: reactjs react-router


【解决方案1】:

localStorage 甚至 cookie 都是选项,但可能不是最好的方法。您应该将计数存储在数据库中,这样您可以将构造函数中的初始状态设置为数据库中保存的最后一个值。

如果您只需要在客户端(而不是在数据库中)持久化计数,另一种选择是使用闭包。

// CountStore.js
var CountStore = (function() {
  var count = 0;

  var incrementCount = function() {
    count += 1;
    return count;
  };

  var getCount = function() {
    return count;
  };

  return {
    incrementCount: incrementCount,
    getCount: getCount
  }

})();

export default CountStore;

因此您的代码将更改为以下内容。

import React, { Component } from 'react';
import CountStore from './CountStore'; 

export default class Foo extends Component {
  state = {
    clickCount: CountStore.getCount()
  };

  componentWillMount() {
    window.onpopstate = (event) => {
      if (event.state.clickCount) {
        this.setState({ clickCount: event.state.clickCount });
      }
    };
  }

  onClick() {
    const newClickCount = CountStore.incrementCount();
    const newState = { clickCount: newClickCount };
    this.setState(newState);
  }

  render() {

    return (
      <div>
        <button onClick={this.onClick.bind(this)}>Click me</button>
        <div>Clicked {this.state.clickCount} times</div>
      </div>
    );
  }
}

可能有更简洁的方式使用react-router,但这是一个选项。

【讨论】:

    【解决方案2】:

    一个例子:

    import React, {Component} from "react";
    import {NavLink} from "react-router-dom";
    
    interface Props {
    }
    
    interface State {
        count: number
    }
    
    export default class About extends Component<Props, State> {
    
        UNSAFE_componentWillMount(): void {
            this.setState(Object.getPrototypeOf(this).constructor.STATE || {});
        }
    
        componentWillUnmount(): void {
            Object.getPrototypeOf(this).constructor.STATE = this.state;
        }
    
        constructor(props: Props) {
            super(props);
            this.state = {count: 0}
        }
    
        render() {
            const {count} = this.state;
            return <div style={{width: "100%", height: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "space-evenly", fontSize: "2em"}}>
                <span>Count: {count}</span>
                <button onClick={() => this.setState({count: count + 1})}>PLUS ONE</button>
                <NavLink to="/">Redirect to HOME</NavLink>
            </div>
        }
    }
    

    【讨论】:

    • 亲爱的@BaiJiFeiLong,请多解释一下。您的代码的解释和代码原因将被更好地理解。也许有更多的赞成票。我对你的帖子投了赞成票。祝你好运。
    • 我认为这是将实例状态存储在类原型上。有点奇怪,但很整洁。
    • 我认为这是将实例状态存储在类原型上。我想可能只有最多 1 个实例,否则它们可能会干扰。有点奇怪但非常整洁。当路由到页面 B 然后返回到 A 时,我使用它来保持页面 A 的状态。react-router 卸载 A,这意味着它的状态将丢失。这是迄今为止我见过的最巧妙的解决方案,用于在 unmount/didmount 中保持 A 的状态。有没有更简洁的解决方案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多