我正在开发一个使用 SSR 的应用程序。它基于 React、Next 和 Redux。我理解拥有客户端存储和服务器端存储并将它们相互同步的一般概念。
我正在使用 next-redux-wrapper 但似乎无法让服务器端存储保持其状态。
_app.js
// pages/_app.js
import React from 'react'
import {Provider} from "react-redux";
import App, {Container} from "next/app";
import withRedux from "next-redux-wrapper";
import makeStore from "../state/index.js";
class MyApp extends App {
static async getInitialProps({Component, ctx}) {
// we can dispatch from here too
// ctx.store.dispatch({type: 'FOO', payload: 'foo'});
const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
return {pageProps};
}
render() {
const {Component, pageProps, store} = this.props;
return (
<Container>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
};
export default withRedux(makeStore, {debug: true})(MyApp)
state/reducers/index.js
import { createStore } from 'redux'
import rootReducer from './reducers/index'
const makeStore = (initialState) => {
return createStore(rootReducer, initialState);
};
export default makeStore;
这是一个页面/index.js(登录)
import React, { Component } from "react";
import Head from 'next/head';
import Input from '@material-ui/core/Input';
// import withRedux from 'next-redux-wrapper';
// import initStore from '../state/index.js';
import { connect } from "react-redux";
const mapStateToProps = state => ({
// Login
paypalCredentials: state.login.paypalCredentials
});
const mapDispatchToProps = dispatch => ({
setPaypalCredentials: (payload) => dispatch({ type: 'SET_PAYPAL_CREDENTIALS', payload: payload })
})
class Login extends Component {
static getInitialProps({store, isServer, pathname, query}) {
// store.dispatch({type: 'FOO', payload: 'foo'}); // component will be able to read from store's state when rendered
// return {custom: 'custom'}; // you can pass some custom props to component from here
}
shouldComponentUpdate(nextProps){
// Redirect if Paypal Details are received (after login)
if (nextProps.paypalCredentials !== this.props.paypalCredentials && nextProps.paypalCredentials !== null) {
window.location.assign("/receipt");
return false;
} else {
return true;
}
}
reqPaypalCredentials = async() => {
let res = await fetch("https://api.paypal.com/v1/oauth2/token?grant_type=client_credentials", {
method: "POST",
'headers': {
'Authorization': 'Basic QVFlY3ZXelNPSE05a3VZSE5WZ2p...confidential',
'Content-Type': 'application/x-www-form-urlencoded'
}
}),
data = await res.json();
return data;
}
submitLogin = () => {
console.log("SubmitLogin");
(async() => {
let data = null,
resolvedData = null;
try {
data = this.reqPaypalCredentials();
resolvedData = await data;
this.props.setPaypalCredentials(resolvedData);
} catch (err) {
console.log("There was an error fetching the data: \n", error);
}
})();
}
forgotPassword = () => {
}
render(){
return (
<React.Fragment>
<Head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/static/css/global.css" />
<link rel="stylesheet" href="/static/css/login.css" />
</Head>
<div id="loginBg">
<div id="loginModal">
<div id="loginHeader">
<h2>Akauntu</h2>
<div id="loginLogo"></div>
<h2>Platform</h2>
</div>
<div id="loginContent">
<div>
<Input
autoFocus={true}
placeholder="Email"
required={true}
type="email"
/>
<Input
placeholder="Password"
required={true}
type="password"
/>
</div>
</div>
<div id="loginFooter">
<h3 onClick={ this.submitLogin }>Login</h3>
</div>
<p onClick={ this.forgotPassword }>Forgot Password?</p>
</div>
</div>
</React.Fragment>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);