Next.js, Graphql, wpgraphql, useMutation hook,material-UI 我尝试构建 WordPress 主题使用 next.js 和 graphql。
我尝试了很多测试,阅读以解决我的错误。
我的域路径:https://blog.rajdeepsingh.dev/graphql
本地服务器:http://localhost:3000/
我的大问题网络错误:JSON 输入意外结束。数据提交时我的注册页面比我的注册组件上显示错误
我将 cors() 库与 express.js 一起使用
我学习
- 标题
- 证书
- 获取选项
- 项目清单
bundle.esm.js:69 POST https://blog.rajdeepsingh.dev/graphql 500
(anonymous) @ bundle.esm.js:69
Subscription @ Observable.js:197
subscribe @ Observable.js:279
(anonymous) @ bundle.esm.js:864
Subscription @ Observable.js:197
subscribe @ Observable.js:279
(anonymous) @ bundle.esm.js:1001
(anonymous) @ bundle.esm.js:998
step @ tslib.es6.js:100
(anonymous) @ tslib.es6.js:81
(anonymous) @ tslib.es6.js:74
__awaiter @ tslib.es6.js:70
push../node_modules/apollo-client/bundle.esm.js.QueryManager.mutate @ bundle.esm.js:950
push../node_modules/apollo-client/bundle.esm.js.ApolloClient.mutate @ bundle.esm.js:2016
push../node_modules/@apollo/react-hooks/lib/react-hooks.esm.js.MutationData.mutate @ react-hooks.esm.js:453
MutationData._this.runMutation @ react-hooks.esm.js:419
submitFormUser @ signup.js:108
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:306
executeDispatch @ react-dom.development.js:389
executeDispatchesInOrder @ react-dom.development.js:414
executeDispatchesAndRelease @ react-dom.development.js:3278
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:3287
forEachAccumulated @ react-dom.development.js:3259
runEventsInBatch @ react-dom.development.js:3304
runExtractedPluginEventsInBatch @ react-dom.development.js:3514
handleTopLevel @ react-dom.development.js:3558
batchedEventUpdates$1 @ react-dom.development.js:21871
batchedEventUpdates @ react-dom.development.js:795
dispatchEventForLegacyPluginEventSystem @ react-dom.development.js:3568
attemptToDispatchEvent @ react-dom.development.js:4267
dispatchEvent @ react-dom.development.js:4189
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
discreteUpdates$1 @ react-dom.development.js:21887
discreteUpdates @ react-dom.development.js:806
dispatchDiscreteEvent @ react-dom.development.js:4168
Show 9 more frames
signup.js:130 undefined " submit Form test maybe workING 4"
signup.js:131 Error: Network error: Unexpected end of JSON input
at new ApolloError (bundle.esm.js:63)
at Object.error (bundle.esm.js:1030)
at notifySubscription (Observable.js:140)
at onNotify (Observable.js:179)
at SubscriptionObserver.error (Observable.js:240)
at bundle.esm.js:869
at Set.forEach (<anonymous>)
at Object.error (bundle.esm.js:869)
at notifySubscription (Observable.js:140)
at onNotify (Observable.js:179)
at SubscriptionObserver.error (Observable.js:240)
at bundle.esm.js:86 " submit Form test maybe error 5"
服务器.js
const express = require( 'express' );
const next = require( 'next' );
const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next( { dev } );
const handle = app.getRequestHandler();
var cors = require('cors')
var corsOptions = {
origin: 'https://blog.rajdeepsingh.dev/',
optionsSuccessStatus: 200
// some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.prepare()
.then( () => {
const server = express();
server.get( '/read/:slug', ( req, res ) => {
const postId = req.params.slug.split( '-' ).pop()
const queryParams = { id: postId };
console.log(queryParams, ' queryParams form server side ')
app.render( req, res, '/read', queryParams );
} );
server.get( '/comment/comment/:slug', ( req, res ) => {
const postId = req.params.slug.split( '-' ).pop()
const queryParams = { id: postId };
app.render( req, res, '/comment', queryParams );
} );
server.get( '/page/page/:slug', ( req, res ) => {
console.log(req.params , ' for server here ')
const postId = req.params.slug.split( '-' ).pop()
const queryParams = { id: postId };
console.log(queryParams , ' queryParams server here side ')
app.render( req, res, '/page', queryParams );
} );
server.get( '/login', ( req, res ) => {
return handle( req, res, '/login' );
} );
server.post( '/signup',cors(corsOptions), ( req, res ) => {
//========================
// show error on signup
//==================
const update= res.json()
return handle( req, update, '/signup' );
} );
server.get( '*', ( req, res ) => {
return handle( req, res );
} );
server.listen( port, ( err ) => {
if ( err ) {
throw err;
}
console.warn( `Ready on http://localhost:${port}` );
} );
} );
阿波罗客户端
import { ApolloClient } from 'apollo-client';
import { InMemoryCache , IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
// import withApollo from 'next-with-apollo';
import { createHttpLink } from 'apollo-link-http';
import fetch from 'isomorphic-unfetch';
import introspectionQueryResultData from '../fragmentTypes.json';
import { HttpLink } from "apollo-link-http";
// whats that fragmentMatcher read here >> https://medium.com/@jacky_ttt/day121-warning-heuristic-fragment-matching-going-on-8208b584cb5e
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
});
const cache = new InMemoryCache({ fragmentMatcher });
// const customFetch = (uri, options) => {
// const { operationName } = JSON.parse(options.body);
// return fetch(`${uri}/graph/graphql?opname=${operationName}`, options);
// };
// const link = createHttpLink({ fetch: customFetch });
const link = new HttpLink({
fetch,
uri: "https://blog.rajdeepsingh.dev/graphql",
credentials: 'same-origin',
fetchOptions:{
mode: 'no-cors',
method:'POST'
},
headers: {
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
}
});
export const client = new ApolloClient({
cache,
link
});
注册组件
import React, { useState } from 'react'
import Layout from '../Component/Layout'
import Card from '@material-ui/core/Card';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Container from '@material-ui/core/Container';
import IconButton from '@material-ui/core/IconButton';
import Input from '@material-ui/core/Input';
import FilledInput from '@material-ui/core/FilledInput';
import OutlinedInput from '@material-ui/core/OutlinedInput';
import InputLabel from '@material-ui/core/InputLabel';
import InputAdornment from '@material-ui/core/InputAdornment';
import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import Visibility from '@material-ui/icons/Visibility';
import VisibilityOff from '@material-ui/icons/VisibilityOff';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import Link from 'next/link'
import style from '../Component/css/Signup.module.scss'
import gql from 'graphql-tag';
import { useMutation } from '@apollo/react-hooks';
export default function Signup(props) {
// mutation query with gql
const getInfoSignup = gql`mutation MyMutation($userData:RegisterUserInput!) {
__typename
registerUser(input:$userData) {
user {
jwtUserSecret
username
userId
}
clientMutationId
}
}
`
const [passward, setPassward] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [showconfirmPassword, setShowconfirmPassword] = useState(false);
const [confirmPassword, setConfirmPassword] = useState("");
const [matchPassward, setMatchPassward] = useState(false);
const [checkbox, setCheckbox] = useState(true);
const [userName, setuserName] = useState("");
const [gmail, setgmail] = useState("");
const [displayName, setDisplayName] = useState("");
// useMutation hook
const [createUser, { data , error} ] = useMutation(getInfoSignup);
// hender error on this way
// Read on stackoverFlow https://stackoverflow.com/questions/59465864/handling-errors-with-react-apollo-usemutation-hook#:~:text=Apollo%20Client%20actually%20provides%20four%20different%20ways%20to%20handle%20mutation%20errors%3A&text=Calling%20the%20mutate%20function%20returned,data%20returned%20by%20the%20server.
// const [createUser, { data, loading, error }] = useMutation(getInfoSignup, {
// variables:{
// userData:{
// username: "RajdeepSingh420",
// email: "RajdeepSingh420@GMAIL.COM",
// password: "RajdeepSingh420",
// revokeJwtUserSecret: true,
// displayName: "Rajdeep Singh 420",
// clientMutationId: "registerUser",
// nicename: "RajdeepSingh420",
// registered: "true",
// }
// },
// onError(err) {
// console.log(err);
// },
// });
// form handler function
const handleChange = (event) => {
setPassward( event.target.value )
};
const handleClickShowPassword = () => {
setShowPassword(!showPassword)
};
const confirmHandleChange = (event) => {
setConfirmPassword( event.target.value)
if( passward === event.target.value ){
setMatchPassward(false)
}else{
setMatchPassward(true)
}
};
const confirmHandleClickShowPassword = () => {
setShowconfirmPassword(!showPassword)
};
const checkboxChange=()=>{
setCheckbox(!checkbox)
}
const handleMouseDownPassword=()=>{
}
const submitFormUser=(event)=>{
event.preventDefault();
createUser(
{
variables:{
userData:{
username: "RajdeepSingh420",
email: "RajdeepSingh420@GMAIL.COM",
password: "RajdeepSingh420",
revokeJwtUserSecret: true,
displayName: "Rajdeep Singh 420",
clientMutationId: "registerUser",
nicename: "RajdeepSingh420",
registered: "true",
}
}
}
);
// for debugging
console.log(createUser , ' inside singup createUser ')
}
// testing show error
console.log(data, ' submit Form test maybe workING 78') // undefined
console.log(error, ' submit Form test maybe error 58') // Network error: Unexpected end of JSON input
return (
<Container className={style.containerBox}>
<Card className={style.root} >
<div className={style.innerCard}>
<div className={style.details}>
<CardContent className={style.cardContentInner}>
<Typography className={style.typeH5} component="h6" variant="h6">
Welcome Back!
</Typography>
<Typography className={style.typeH3} component="h3" variant="h2">
Learn With Me
</Typography>
<form
// on Submit handler
onSubmit={submitFormUser}
className={style.form}
noValidate autoComplete="off"
>
<TextField onChange={(e)=>setDisplayName(e.target.value)} id="fullName" className={style.textControl} placeholder=' Exmple:Rajdeep Singh ' label="Full Name" />
<TextField onChange={(e)=>setuserName(e.target.value)} id="userName" className={style.textControl} placeholder=' Exmple:Officialrajdeepsingh ' label="User Name" />
<TextField onChange={(e)=>setgmail(e.target.value)} id="userGmail" className={style.textControl} placeholder=' 123@gmail.com ' label="Gmail" />
<FormControl className={style.textControl} >
<InputLabel htmlFor="password">Password</InputLabel>
<Input
id="password"
type= {showPassword ? 'text' : 'password'}
value={passward}
onChange={handleChange}
placeholder='Exmple: Rb@1%2^3*56'
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<FormControl className={style.textControl} >
<InputLabel htmlFor="confirmPassword">Confirm Password</InputLabel>
<Input
id="confirmPassword"
type= {showconfirmPassword ? 'text' : 'password'}
value={confirmPassword}
onChange={confirmHandleChange}
error={matchPassward}
paceholder='Exmple Confirm Passward : Rb@1%2^3*56'
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={confirmHandleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<FormControlLabel
control={
<Checkbox
checked={checkbox}
onChange={checkboxChange}
name="checkBox"
color="primary"
className={ style.checkBox }
/>
}
label="I Agree to Terms & Conditions "
/>
<Button type="submit"
// send data on this button
className={style.productButton} size="small">
Submit
</Button>
</form>
</CardContent>
<div className={style.typeLogin}>
<>
<Typography className={style.anchorLink} component="h6" variant="h6">
Login With Me
</Typography>
<Link href="/login">
<a> Click Here </a>
</Link>
</>
</div>
</div>
<CardMedia
component="img"
alt="Contemplative Reptile"
image='https://source.unsplash.com/random'
title="Live from space album cover"
className={style.cardImage}
/>
</div>
</Card>
</Container>
)
}