在使用react搭配react-router做应用的时候,你可能遇到这样的问题,当我从第一个页面过渡到第二个页面,然后返回之后,发现之前的页面的状态全部不见了,即回到了初始的状态。

这点在页面存在多个TAB页或者多条件筛选的时候体验会更加明显,这时候我又不得不点击我之前选择的页签,重新选择筛选条件,然后再进行搜索。因此,在这种情况下,保存之前的状态显得尤为亟待解决,下面是自己实践出来的几种方法,做一下分享,同时希望和各位一起探讨,看能不能有什么更好的办法。

代码:github

解决方案一:子路由方式

// normal/routers/Books/Books.js
module.exports = {path: 'books',getComponent(nextState, cb) {require.ensure([], (require) => {cb(null, require('./components/Books'))})},getChildRoutes(partialNextState, cb) {require.ensure([], (require) => {cb(null, [require('./book')])    })}
};// normal/routers/Books/book.js
module.exports = {path: 'book/:id',getComponent(nextState, cb) {require.ensure([], (require) => {cb(null, require('./components/Book'))})}
};

配置图书列表下的嵌套路由可以查看图书详情。具体的路由跳转如下:

// normal/routers/Books/components/Books.jsonLookDetail(id, book, index) {this.setState({ activeIndex: index });this.props.router.push({ pathname: `books/book/${id}`, query: book });
}render() {const { children } = this.props;// ...// 如果有字路由组件,就渲染子组件if (children) {return children;}// ...
}

效果如下:

可以看到,当从详情页面返回时,点击的激活状态依旧可以保存,但是列表滚动的高度并不能够保存,关于高度的恢复在下面会讲到。

解决方案二:当前页面弹窗

不占用路由,在当前页面直接已弹窗的形式加载详情页面。

// normal/routers/Books/components/Books.js
constructor(props) {super(props);this.state = {activeIndex: -1,books: [],modal: false};
}onLookDetail(id, book, index) {this.setState({ activeIndex: index, modal: true });
}onDetailBack() {this.setState({ modal: false });
}render() {{// 根据state中的modal值来判断当前弹窗是否显示// 其实就是Book.js中的代码modal && (<div style={ styles.modal }><Flex direction="column" style={ styles.wrapper }><div style={ styles.header }><NavBar mode="dark"leftContent="返回"icon={<Icon type="left" />}onLeftClick={ this.onDetailBack.bind(this) }>图书详情</NavBar></div><div style={ styles.content }><Card><Card.Headertitle="标题"thumb="xxx"extra={ <span>{ book.title }</span> }/><Card.Body><div>{ book.description }</div></Card.Body><Card.Footer content="footer content" extra={<div>{ book.price }</div>} /></Card></div></Flex></div>)}
}

效果如下:

看上去效果十分好,既能保存状态,也能保存滚动条的高度。

解决方案三:本地存储/redux数据仓库/参数传递

我把这三种方案归结为一种,因为实际上是在离开列表组件的时候保存当前的状态,然后在回到页面的时候根据之前保存的状态来进行现场恢复而已。

// src/routers/Books/components/Books.js// 配合shouldComponentUpdate声明周期函数,避免不必要的渲染
shouldComponentUpdate(nextProps, nextState) {return !is(fromJS(this.props.books), fromJS(nextProps.books))|| !is(fromJS(this.state), fromJS(nextState));
}// 更新当前选中的activeIndex值,将其同步至redux中,然后再进行路由跳转
onLookDetail(id, book, index) {const { actions } = this.props;actions.updateBooks({ activeIndex: index });this.props.router.push({ pathname: `book/${id}`, query: book });
}// 从redux中取值进行现场恢复
render() {const { books } = this.props;const list = books.books;const activeIndex = books.activeIndex;// ...
}// src/reudx/reudcers/books.js
const initialState = {books: [],activeIndex: -1
};

效果如下:

效果和字路由方式相同,依然存在滚动高度不能保存的问题。

滚动高度问题

下面来谈谈如何解决滚动高度的问题,综合起来还是一种恢复现场的方式。在页面即将离开之前,保存之前的scrollTop值,然后再次回到这个页面的时候,恢复滚动高度即可。

// src/reudx/reudcers/books.js
const initialState = {books: [],activeIndex: -1,// 添加scrollTopscrollTop: 0
};// src/routers/Books/components/Books.js
componentDidMount() {const { actions, books } = this.props;const content = this.refs.content;const scrollTop = books.scrollTop;if (scrollTop > 0) {content.scrollTo(0, scrollTop);}setTimeout(() => {actions.getBooks();}, 150);
}componentWillUnmount() {const content = this.refs.content;const { actions } = this.props;actions.updateBooks({ scrollTop: content.scrollTop });
}

效果如下:

尝试方案:react-keeper

github上搜索看到了这个库,类似于react-router的一个翻版,同时在react-router的基础上增加了类似于vue-router中的keep-alive功能,这点暂时占坑,等做了案例之后再来填坑。

转载于:https://www.cnblogs.com/rynxiao/p/8305017.html

关于React中状态保存的研究相关推荐

  1. Android Activity中状态保存机制

    在Activity中保存用户的当前操作状态,如输入框中的文本,一般情况下载按了home键后,重新进入文本框中的东西会丢下,所以我们要保存当前页面信息,如在写短信的时候接到一个电话,那么当你接电话的时候 ...

  2. react中状态提升是什么意思

    就是把子组件的状态交给父组件去管理. 意思就是子组件的状态是通过this.props.state拿到的.

  3. react怎么存上一页_如何实现 React 中的状态自动保存?

    什么是状态保存? 假设有下述场景: 移动端中,用户访问了一个列表页,上拉浏览列表页的过程中,随着滚动高度逐渐增加,数据也将采用触底分页加载的形式逐步增加,列表页浏览到某个位置,用户看到了感兴趣的项目, ...

  4. react中的状态机_在基于状态图的状态机上使用React的模式

    react中的状态机 by Shawn McKay 肖恩·麦凯(Shawn McKay) 在基于状态图的状态机上使用React的模式 (Patterns for using React with St ...

  5. react中数据状态管理的四种方案

    我们为什么需要状态管理? (1) 一个是为了解决相邻组件的通信问题. 虽然可以通过「状态提升」解决,但有两个问题: 每次子组件更新,都会触发负责下发状态的父组件的整体更新(使用 Context 也有这 ...

  6. 如何在React中从其父组件更改子组件的状态

    by Johny Thomas 约翰尼·托马斯(Johny Thomas) 如何在React中从其父组件更改子组件的状态 (How to change the state of a child com ...

  7. [react] 在react中怎样改变组件状态,以及状态改变的过程是什么?

    [react] 在react中怎样改变组件状态,以及状态改变的过程是什么? 使用this.setState改变组件的状态 改变的过程中,React Fiber Reconciler遍历了整个Fiber ...

  8. [react] 在react中你是怎么进行状态管理的?

    [react] 在react中你是怎么进行状态管理的? 使用React原生的Context+useContext(可选的加上useReducer) 使用redux + react-redux + re ...

  9. [react] 描述下在react中无状态组件和有状态组件的区别是什么?

    [react] 描述下在react中无状态组件和有状态组件的区别是什么? 1,无状态组件主要用来定义模板,接收来自父组件props传递过来的数据,使用{props.xxx}的表达式把props塞到模板 ...

最新文章

  1. Elixir: 多太(Polymorphism)
  2. Socket编程获取服务器时间
  3. java的初始,Java初始
  4. C Runtime Library 的来历
  5. lightoj 1026 无向图 求桥
  6. python的pyqt5_Pycharm+Python+PyQt5使用详解
  7. Unity3d LookAt参数说明
  8. 逻辑回归预测事件发生的概率_通过逻辑回归,对信用卡申请数据使用卡方分箱法预测违约率建模...
  9. 图片格式之YUV420 转RGB格式(含代码)
  10. 小程序文章怎么导出来_微信小程序点餐怎么申请,怎么建立微信点单小程序
  11. 报错注入是什么?一看你就明白了。报错注入原理+步骤+实战案例
  12. 深入浅出redux知识
  13. 中兴盒子B860A-免拆机-线刷-第三方刷机固件及教程
  14. php解析乱码字符串,php中文字符串截取方法防止乱码解析
  15. Python中的shuffle()函数
  16. 存储过程——身份证校验
  17. 在K8s上轻松部署Tungsten Fabric的两种方式
  18. PyTorch训练中Dataset多线程加载数据,比Dataloader里设置多个workers还要快
  19. ATmega16智能遥控小车
  20. 数学公式公式获取工具 Mathpix snipping Tool

热门文章

  1. mso-number-format
  2. (转载)SQL高级查询技巧
  3. 解决Cannot load /usr/local/apache/modules/libphp5.so的方法
  4. Hiernate概述
  5. JS获取登录者IP和登录城市
  6. 用 Gearman 分发 PHP 应用程序的工作负载(转载)
  7. 自动化运维工具Ansible实战(四)常用模块
  8. [Coding Style] CSS coding style
  9. MapReduce的基本流程
  10. iOS -- 音频播放、录音、视频播放、拍照、视频录制