[cc lang=”js”]
// 本地和服务器验证
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
export default (async function asyncValidate(values /*, dispatch */) {
await sleep(1000); // simulate server latency
if ([“foo@foo.com”, “bar@bar.com”].includes(values.email)) {
return { email: “Email already Exists” };
}
});
export default reduxForm({
form: ‘MaterialUiForm’, // a unique identifier for this form
validate,
asyncValidate,
})(MaterialUiForm);[/cc]
初始化 表单数据
[cc lang=”js”]InitializeFromStateForm = reduxForm({
form: ‘initializeFromState’, // a unique identifier for this form
})(InitializeFromStateForm);
// You have to connect() to any reducers that you wish to connect to yourself
InitializeFromStateForm = connect(
state => ({
initialValues: state.account.data, // pull initial values from account reducer
}),
{ load: loadAccount }, // bind account loading action creator
)(InitializeFromStateForm);[/cc]
——————————————————————
5 警告错误 : Warning: React does not recognize the `basePath` prop on a DOM element.
If you intentionally want it to appear in the DOM as a custom
attribute, spell it as lowercase `basepath` instead. If you
accidentally passed it from a parent component, remove it from the DOM
element.
In order to get rid of the basePath error, just sanitize the props passed to the Material UI Grid Component:
export default Post
///post/abc?foo=bar will have the query object: { foo: ‘bar’, pid: ‘abc’ }.
[/cc]
Any route like /post/1, /post/abc, etc will be matched by pages/post/[pid].js.
拦截器 popstate
你可能想监听popstate,在路由跳转前做一些动作。 比如,你可以操作 request 或强制 SSR 刷新
[cc lang=”js”]
import Router from ‘next/router’
Router.beforePopState(({ url, as, options }) => {
// I only want to allow these two routes!
if (as !== “/” || as !== “/other”) {
// Have SSR render bad routes as a 404.
window.location.href = as
return false
}
//如果路由加载被取消(比如快速连续双击链接)
Router.events.on(‘routeChangeError’, (err, url) => {
if (err.cancelled) {
console.log(`Route to ${url} was cancelled!`)
}
})
[/cc]
浅层路由
浅层路由允许你改变 URL 但是不执行getInitialProps生命周期。你可以加载相同页面的 URL,得到更新后的路由属性pathname和query,并不失去 state 状态。
注意: 浅层路由只作用于相同 URL 的参数改变,
[cc lang=”js”]// Current URL is “/”
const href = ‘/?counter=10’
const as = href
Router.push(href, as, { shallow: true })
//在组件里查看this.props.router.query你将会看到更新的 URL。
[/cc]
你可以在componentdidupdate钩子函数中监听 URL 的变化。
[cc lang=”js”]componentDidUpdate(prevProps) {
const { pathname, query } = this.props.router
// verify props have changed to avoid an infinite loop
if (query.id !== prevProps.router.query.id) {
// fetch data based on the new query
}
}[/cc]
禁止文件路由
默认情况,Next将会把/pages下的所有文件匹配路由(如/pages/some-file.js 渲染为 site.com/some-file)
[cc lang=”js”]
// next.config.js
module.exports = {
useFileSystemPublicRoutes: false
}
// 注意useFileSystemPublicRoutes只禁止服务端的文件路由;但是客户端的还是禁止不了。
//可以通过 配置客户端路由不能跳转文件路由
import Router from ‘next/router’
Router.beforePopState(({ url, as, options }) => {
// I only want to allow these two routes! zhi
if (as !== ‘/’ || as !== ‘/other’) {
// Have SSR render bad routes as a 404.
window.location.href = as
return false
}
等。如果想自定义文档标记,你可以新建./pages/_document.js,然后扩展Document类:
[cc lang=”js”]// _document is only rendered on the server side and not on the client side
// Event handlers like onClick can’t be added to this file
1. Webpack can’t statically analyze what’s inside eval. So it won’t bundle the faker module.
[cc lang=”js”]const faker = eval(“require(‘faker’)”)[/cc]
2. Create a file called next.config.js in your Next.js app and add the webpack IgnorePlugin.
[cc lang=”js”]module.exports = {
webpack: function (config) {
config.plugins.push(
new require(‘webpack’).IgnorePlugin(/faker/)
)
return config
}
}[/cc]
3. USING THE “BROWSER” FIELD OF THE “PACKAGE.JSON”
You can also ask webpack to disable bundling faker module via adding a config in the main package.json file.
Add the following code in to your package.json file.
[cc lang=”js”]{
…
“browser”: {
“faker”: false
}
…
}[/cc]
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
npm test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
npm run build
Builds the app for production to the build folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
npm run eject
Note: this is a one-way operation. Once you eject, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
import ApolloClient from'apollo-boost';const client =newApolloClient({
uri:'https://48p1r2roz4.sse.codesandbox.io',});
import{ gql }from"apollo-boost";// or you can use `import gql from 'graphql-tag';` instead...
client
.query({
query: gql`
{
rates(currency: "USD") {
currency
}
}
`}).then(result=> console.log(result));
Connect your client to React
用到ApolloProvider ,
!!! 如果用到react-router 一般会在包裹在 root route 组件外层
import{ ApolloProvider }from'@apollo/react-hooks';constApp=()=>(<ApolloProviderclient={client}><div><h2>My first Apollo app ?</h2></div></ApolloProvider>);