从零搭建一个基于React+Nextjs的SSR网站(二):在Nextjs项目中增加react+redux

2,321 阅读2分钟

PS: 如果你有疑惑,可以给我留言,咱们一起解决它。

从零搭建一个基于React+Nextjs的SSR网站(一):写在前面

从零搭建一个基于React+Nextjs的SSR网站(二):在Nextjs项目中增加react+redux

从零搭建一个基于React+Nextjs的SSR网站(三):在Next项目中使用markdown

从零搭建一个基于React+Nextjs的SSR网站(四):如何搭建服务器并部署Nextjs项目

正文

基本的Nextjs项目构造可以参考这篇文章,写得很好也非常详细,我就不转载了:

用Next.js快速上手React服务器渲染

看完上面的这篇文章后你会搭建一个自己的本地的静态站点,并且可以运行在localhost:3000。这个时候我们就可以向这个项目上面添加React和Redux了。

与往常的react+redux项目不同的是,以往的react的组件是用Provider容器包裹起来的,可以让容器组件拿到state,比如下面这样

...
import { Provider } from 'react-redux'
import { 
	BrowserRouter, 
	Route, 
	Switch
} from 'react-router-dom'
...

<Provider store={store}>
	<BrowserRouter>
		<div className="XXX">
			<Component1 />
			<Switch>
				<Route path='/path1' exact component={Component1} />
				<Route path='/path2' exact component={Component2} />
			</Switch>
		</div>
	</BrowserRouter>
</Provider>

不过在Nextjs中,不能这么写,Next提供了全局的容器Container。既然用了Next,那就用它提供的方式去解决吧。比如下面这样:

...
import {Container} from 'next/app';
import {Provider} from 'react-redux'
import {withRouter} from 'next/router'
...
@withRouter

class MyApp extends App {
	
  constructor(props) {
    ...
  }
  ...
  render () {
    ...
    return (
      <Container>
            <Provider store={reduxStore}>
                <FrontLayout>
                    <Component {...pageProps} />
                </FrontLayout>
            </Provider>
      </Container>
    );
  }
  
}

export default MyApp

这里的@withRouter是装饰器写法,是一个对类进行处理的函数。修饰器函数的第一个参数,就是所要修饰的目标类。

用代码解释大致是下面这样:

@withRouter
class A {}
// 等于下面这么写
class A {}
A = withRouter(A) || A;

然后你就可以在你的Next项目中使用react+redux了

title-redux.js示例:

const TOGGLE_TITLE = 'TOGGLE_TITLT';

const titleState = {
    currentTitle: 'Soy的个人网站'
}

export function TitleReducer(state=titleState, action) {
    switch (action.type){
        case TOGGLE_TITLE:
            return {...state, currentTitle: action.title}
        default:
            return state;
    }
}

export function toggleDispatch(title = titleState.currentTitle){ 
    return {type: TOGGLE_TITLE, title}
}

reducer.js示例:

import { combineReducers } from 'redux'
import { TitleReducer } from './redux/title-redux';

export default combineReducers({TitleReducer})

store.js示例:

import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import reducers from './reducer'
import {composeWithDevTools} from 'redux-devtools-extension'

export function initializeStore(initialState = {}) {
	return createStore(reducers, initialState, composeWithDevTools(applyMiddleware(thunkMiddleware)))
}

博客源码:github.com/shaotianyu/…