When implementing single-page applications with React and React-Router, there is a scenario where clicking on an item from the list page leads to the details page, and when you go back to the list page, the list page is refreshed again, with the data retrieved and the scroll bar back to the top. To continue to see the rest of the data, users need to swipe back to the item they clicked on earlier, which is even more troublesome if the list is paginated, which is very bad for the user experience.
So we want to be able to go back from the secondary page to the list page and leave the list page in its previous state (data and scrollbar position).
So how do you do that? React uses redux to cache list data and slide positions to preserve list page state.
Use of Redux and React-Redux will not be explained here. You can refer to the principle and use of React-Redux I wrote earlier. Of course, there are plenty of articles on the Web that are more clearly explained and readers can search for them.
Let’s dive right into the steps to implement the requirements
Install redux and React-redux
cnpm install redux react-redux -dev –save
2, write action list page related data
/** * Created by RaoMeng on 2018/12/10 * Desc: list data cache */ import {CLEAR_LIST_STATE, LIST_STATE} from".. /constants/actionTypes";
import store from '.. /store/store'/** * save list state * @param data * @returns {Function} */export const saveListState = (data) => {
return () => {
store.dispatch({
type: LIST_STATE, ... Data})}} /** * clear list state * @returns {Function} */export const clearListState = () => {
return () => {
store.dispatch({
type: CLEAR_LIST_STATE
})
}
}
Copy the code
There are two ActionTypes implemented here, one is to save the list state, one is to clear the list state. The state of the list is saved so that the page is not refreshed during the rollback. If you do not clear the cached data in redux, the page will read the cached data and will not request network data again. Therefore, this action is also necessary.
3. Achieve reducer of action operation state
import {CLEAR_LIST_STATE, LIST_STATE} from ".. /constants/actionTypes"; Const initListState = {scrollTop: 0,// listData: [],// listData pageIndex: 1,// -1,// index} const redListState = (state = initListState, action) => {if (action === undefined) {
return state
}
switch (action.type) {
caseLIST_STATE: // Updates the list statereturn{... state, ... action }caseCLEAR_LIST_STATE: // Clears list statereturn initListState
default:
return state
}
}
export default redListState
Copy the code
/** * Created by RaoMeng on 2018/12/10 * Desc: import {combineReducers} from'redux'
import redUserInfo from './redUserInfo'
import redListState from './redListState'
import redClassData from './redClassData'
const reducers = combineReducers({redUserInfo, redListState, redClassData})
export default reducers
Copy the code
Here’s why you should record the page number and click on the item index. Recording paging page numbers is only needed if the list data is paginated. This is so that the page number is correct when the user continues to pull up and load data after going back to the list page. The index of the clicked item is recorded so that the clicked item data can be updated on the details page. For example, in a meeting check-in list, the user clicks on a certain item of data to enter the detail page and then clicks on the check-in button. At this time, we need to call the *saveListState()()* method of action to update the corresponding data in the cache and change the status of the item to check-in. The data will be displayed correctly when you go back to the list page.
4. Create store
import {createStore} from 'redux'
import reducers from '.. /reducers/index'
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const persistConfig = {
key: 'root', storage: storage, stateReconciler: autoMergeLevel2'Merge Process'Part of the specific}; const myPersistReducer = persistReducer(persistConfig, reducers) const store = createStore(myPersistReducer)export const persistor = persistStore(store)
export default store
Copy the code
Redux-persist is used to persist redux data. Redux-persist is used to persist redux data.
5. Call the saveListState method in the callback event for clicking on the item to save the list state
< parent layout ref={el => {this.container = el}} > </ parent layout > onItemClick = index => {console.log('scrollTop', ReactDOM.findDOMNode(this.container).scrollTop)
saveListState({
scrollTop: ReactDOM.findDOMNode(this.container).scrollTop,
listData: this.state.meetingSignList,
pageIndex: mPageIndex,
itemIndex: index,
})()
const {meetingSignList} = this.state
this.props.history.push('/meet-detail/' + meetingSignList[index].meetId)
}
Copy the code
Get the slide distance of the parent layout by reactdom.finddomNode (this.container).scrolltop
Get the REdux data in the page’s componentDidMount method
First, the data in state is bound to props of the page through the connect method of React-Redux for easy access
letmapStateToProps = (state) => ({ listState: {... state.redListState} })let mapDispatchToProps = (dispatch) => ({})
export default connect(mapStateToProps, mapDispatchToProps)(MeetingSignIn)
Copy the code
This way, the list data cached in Redux can be accessed on the page through this.props. ListState
Then, get the cached list data in componentDidMount, load it if there is cached data, and re-request it if there is none
componentDidMount() {
document.title = 'Meeting Management'
console.log('listState', this.props.listState)
if(this.props.listState && ! isObjEmpty(this.props.listState.listData)) { this.setState({ meetingSignList: this.props.listState.listData, isLoading:false,}, () => { ReactDOM.findDOMNode(this.container).scrollTop = this.props.listState.scrollTop }) mPageIndex = this.props.listState.pageIndex }else {
Toast.loading('Data loading... ', 0)
mPageIndex = 0
this.loadMeetList()
}
}
Copy the code
React uses redux to cache list data and slide positions to restore page state when it falls back.