My brain broke. Why server send this error.I looked through all the articles with the same error and did not find a solution. What is the problem? How i can fixed this error? Please help.
My code.
App.jsx
This is client for Apollo Client
const client = new ApolloClient({
uri: "http://localhost:4000/api/",
request: (operation) => {
const token = localStorage.getItem("token");
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : ""
}
});
}
});
signUp.js
This is mutation for sighUp
import { gql } from "apollo-boost";
export default gql`
mutation signup($firstName: String!, $secondName: String!, $email: String!, $password: String! ) {
signup(firstName: $firstName, secondName: $secondName, email: $email, password: $password )
}
`;
RegForm.jsx
It is my component registration
import React, {Component} from 'react'
import {Field, reduxForm, SubmissionError} from 'redux-form'
import regForm from './RegForm.module.css'
import { matchInput, passLength, email, required} from '../../../utils/validators'
import RegMutation from '../../../queries/signup'
import Button from '../../../UI/Button/Button'
import myInput from '../../../UI/Input/Input'
import { withMutation } from "react-apollo";
const passwordValidator = passLength(8);
class RegForm extends Component {
constructor(props){
super(props)
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(fields) {
console.log('Fields from handleSubmit',fields);
const { mutate } = this.props;
return new Promise((resolve, reject) => {
mutate({
variables: {
firstName: fields.loginField,
email: fields.email,
password: fields.passwordField
}
})
.then(res => {
console.log(res.data);
resolve(res);
})
.catch(e => {
reject(new SubmissionError({ _error: e?.message }));
});
});
}
render(){
return (
<div>
<form
className={regForm.formContent}
onSubmit={this.props.handleSubmit(this.handleSubmit)}
>
<Field
name='loginField'
type='text'
component={myInput}
validate={[required]}
/>
<Field
name='email'
type='text'
component={myInput}
validate={[email]}
/>
<Field
name='passwordField'
type='password'
component={myInput}
validate={[passwordValidator]}
placeholderText='Введите пароль'
/>
<Field
name='repPas'
type='password'
component={myInput}
validate={[matchInput]}
/>
<Button
onClick={this.Click}
className={regForm.button}>Sign Up
</Button>
</form>
{this.props.error ? <span>{this.props.error}</span> : null}
</div>
)
}
}
const connectedToReduxForm = reduxForm({
form: "loginForm",
});
export default withMutation(RegMutation)(connectedToReduxForm(RegForm))
secondName field is absent. I've known about this one by running full the project)
screenshot
Related
my problem is quite strange. When I call a query in graphiql it works. As soon as I do it in my React app it doesn't. Question marked in code: When I log just dataCategories I get the object. When I try to log dataCategories.allCategories then I get the error "dataCategories undefined". I absolutely have no clue what is going on here...
const NEW_TWEET = gql`
mutation createTweet($title: String!, $content: String!) {
createTweet(input: { title: $title, content: $content }) {
_id
title
content
date
}
}
`;
const TWEETS_QUERY = gql` {
allTweets {
_id
title
content
date
}
}`;
const CATEGORIES_QUERY = gql` {
allCategories {
_id
label
}
}`;
const NewTweet = () => {
let history = useHistory();
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [createTweet] = useMutation(NEW_TWEET, {
update(
cache,
{data: {createTweet}}
) {
const {allTweets} = cache.readQuery({ query: TWEETS_QUERY });
cache.writeQuery({
query: TWEETS_QUERY,
data: { allTweets: allTweets.concat([createTweet])}
});
}
});
const { loading: loadingCategories, error: errorCategories, data: dataCategories } = useQuery(CATEGORIES_QUERY);
console.log(dataCategories));
////// When I log just dataCategories I get the object. When I try to log dataCategories.allCategories then I get the errer "dataCategories undefined".
return (
<div className="container m-t-20">
<h1 className="page-title">New Tweet</h1>
<div className="newnote-page m-t-20">
<form onSubmit={e => {
e.preventDefault();
createTweet({
variables: {
title,
content,
date: Date.now()
}
});
notify.show("Tweet was created succuessfully.", "success")
history.push('/');
}
}>
<div className="field">
<label className="label">Tweet Title</label>
<div className="control">
<input name="title" className="input" type="text" placeholder="Tweet Title" value={title} onChange={e => setTitle(e.target.value)} />
</div>
</div>
<div className="field">
<label className="label">Tweet Content</label>
<div className="control">
<textarea name="content" className="textarea" rows="10" placeholder="Tweet Content here..." value={content} onChange={e => setContent(e.target.value)}></textarea>
</div>
{/*} <Autocomplete
multiple
id="tags-outlied"
options={dataCategories.allCategories}
getOptionLabel={(option) => option.label}
filterSelectedOptions
renderInput={(params) => (
<TextField
{...params}
label="Kategorien"
placeholder="Kategorien"
/>
)}
/>*/}
<div className="field">
<div className="control">
<button className="button is-link">Submit</button>
</div>
</div>
</form>
</div>
</div>
);
}
export default NewTweet;
The schema is:
import { makeExecutableSchema } from "#graphql-tools/schema";
import { resolvers } from "./resolvers";
const typeDefs = `
type Tweet {
_id: ID!,
title: String!,
date: Date,
content: String!
}
scalar Date
type Category {
_id: ID!,
label: String!
}
type Query {
getTweet(_id: ID!) : Tweet
allTweets : [Tweet]
getCategory(Cat: ID!) : Category
allCategories : [Category]
}
input TweetInput {
title: String!,
content: String!
}
input CategoryInput {
label: String!
}
input TweetUpdateInput {
title: String,
content: String
}
type Mutation {
createTweet(input: TweetInput) : Tweet
updateTweet(_id: ID!, input: TweetUpdateInput) : Tweet
deleteTweet(_id: ID!) : Tweet
createCategory(input: CategoryInput) : Category
deleteCategory(_id: ID!) : Category
}
`;
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
export default schema;
The resolvers are:
import Category from './models/category'
export const resolvers = {
Query : {
async getTweet(root, { _id }) {
return await Tweet.findById(_id);
},
async allTweets() {
return await Tweet.find();
},
async getCategory(root, {_id}) {
return await Category.findById(_id);
},
async allCategories() {
return await Category.find();
}
},
Mutation : {
async createTweet(root, { input }) {
return await Tweet.create(input);
},
async updateTweet(root, { _id, input }) {
return await Tweet.findOneAndUpdate({_id}, input, {new: true});
},
async deleteTweet(root, {_id}) {
return await Tweet.findOneAndRemove({_id});
},
async createCategory(root, { input }) {
return await Category.create(input);
},
async deleteCategory(root, {_id}) {
return await Category.findOneAndRemove({_id});
}
}
}
Assuming there is no error in the query, this seems to be quite normal. The first time React renders your component, the query will not have fired. And then it may be in flight (so loadingCategories would be true). You should never assume that the results from a query (data) will not be null/undefined. You should always guard against it and display an appropriate UI unless/until data is not null.
Here's the GraphQL Query:
const movieByName = gql`
query SomeName($name: String!){
movieByName(name: $name){
name
genre
year
}
}`
It works fine on graphiql though and here's the Schema
type Query {
movies: [Movie],
movieByName(name: String!): Movie
}
type Movie {
name: String,
genre: String,
year: String
}
Here's the final code file:
import React, { Component } from 'react';
import {HashLink as Link} from 'react-router-hash-link'
import { graphql } from 'react-apollo';
import { gql } from "apollo-boost";
const movieByName = gql`
query SomeName($name: String!){
movieByName(name: $name){
name
genre
year
}
}`
class Header extends Component {
state = {
name: '',
genre: '',
year: ''
}
searchSubmit = (event) => {
event.preventDefault()
console.log(this.props)
}
render(){
return (
<div className="topnav">
<a className="logo" href="/">Movie Maker</a>
<div className="search-container">
<form onSubmit={this.searchSubmit}>
<Link smooth to="#form">Add Movies</Link>
<input type="text" placeholder="Search.." name="search"
onChange={(e) => this.setState({name: e.target.value})}/>
<button type="submit"><i className="fa fa-search"></i></button>
</form>
</div>
</div>
);
}}
export default graphql(movieByName)(Header)
I'm very new to React Apollo and graphQL. I'm trying to create an edit profile form that adds data to the users profile. When I click submit nothing happens and get get errors in the console log:
Ideally I would like the form to initially render with any data that the user has previously entered so that when the form is submitted and they haven't changed all the inputs, the inputs they haven't changed aren't overwritten in the mongoDB database.
All and any advise would be much appreciated! Thank You!
POST http://localhost:3000/graphql 400 (Bad Request)
[GraphQL error]: Message: Variable "$email" is not defined., Location: [object Object],[object Object], Path: undefined
[GraphQL error]: Message: Variable "$locationCity" is not defined., Location: [object Object],[object Object], Path: undefined
[GraphQL error]: Message: Variable "$locationState" is not defined., Location: [object Object],[object Object], Path: undefined
[GraphQL error]: Message: Variable "$locationCountry" is not defined., Location: [object Object],[object Object], Path: undefined
[GraphQL error]: Message: Variable "$interests" is not defined., Location: [object Object],[object Object], Path: undefined
[Network error]: ServerError: Response not successful: Received status code 400
In my schema.js I have the following:
editOtherProfileDetails(email: String!, locationCity: String!, locationState: String!, locationCountry: String!, interests: String!): User
In my resolvers.js I have the following:
editOtherProfileDetails: async (root, { email, locationCity, locationState, locationCountry, interests }, { User }) => {
const user = await User.findOneAndUpdate({ email },
{ $set: { locationCity: locationCity } },
{ $set: { locationState: locationState } },
{ $set: { locationCountry: locationCountry } },
{ $set: { interests: interests } },
{ new: true }
);
if (!user) {
throw new Error('User Not Found');
}
return user;
},
In my index.js I have:
export const EDIT_OTHER_PROFILE_DETAILS = gql`
mutation($locationCountry: String!){
editOtherProfileDetails(email: $email, locationCity: $locationCity, locationState: $locationState, locationCountry: $locationCountry, interests: $interests){
email
locationCity
locationState
locationCountry
interests
}
}
`;
In my editProfile.js I have the following:
import React, { Fragment } from 'react';
import { Mutation } from 'react-apollo';
import {GET_USER_PROFILE, EDIT_OTHER_PROFILE_DETAILS, PROFILE_PAGE } from './../../queries';
import { withRouter } from 'react-router-dom';
import toastr from 'toastr';
const initialState = {
locationCity: '',
locationState: '',
locationCountry: '',
interests: '',
error: ''
}
class EditOtherProfileMutations extends React.Component {
constructor(props) {
super(props);
this.state = {
locationCity: '',
locationState: '',
locationCountry: '',
interests: '',
error: ''
}
}
componentDidMount() {
if (this.props.profile) {
this.setState({
locationCity: this.props.profile.locationCity,
locationState: this.props.profile.locationState,
locationCountry: this.props.profile.locationCountry,
interests: this.props.profile.interests
});
}
toastr.options = {
"closeButton": false,
"debug": false,
"newestOnTop": true,
"progressBar": true,
"positionClass": "toast-bottom-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
}
handleChange(event) {
const name = event.target.name;
const value = event.target.value;
this.setState({
[name]: value.charAt(0).toUpperCase() + value.substr(1).toLowerCase()
});
}
handleSubmit(event, editOtherProfileDetails) {
event.preventDefault();
editOtherProfileDetails().then(async () => {
toastr.success('We have updated your details!', 'Saved!');
}).catch(error => {
this.setState({
error: error.graphQLErrors.map(x => x.message)
})
// console.error("ERR =>", error.graphQLErrors.map(x => x.message));
});
}
render() {
const { locationCity, locationState, locationCountry, interests } = this.state
const userName = this.props.session.getCurrentUser.userName;
this.state;
return (
<Fragment>
<Mutation
mutation={EDIT_OTHER_PROFILE_DETAILS}
variables={{ email: this.props.session.getCurrentUser.email, locationCity, locationState, locationCountry, interests }}
refetchQueries={() => [
{ query: GET_USER_PROFILE },
{ query: PROFILE_PAGE, variables: { userName } }
]}>
{/* eslint-disable */}
{(editOtherProfileDetails, { data, loading, error }) => {
/* eslint-enable */
return (
<form className="form" onSubmit={event => this.handleSubmit(event, editOtherProfileDetails)}>
<div className="form_wrap">
<div className="form_row">
<div className="form_item">
<div className="form_input">
<span className="edit_profile_span">City</span>
<input type="text" name="locationCity" placeholder="City" value={locationCity} style={{ textTransform: "capitalize"}} onChange={this.handleChange.bind(this)}/>
<span className="bottom_border"></span>
</div>
</div>
</div>
<div className="form_row">
<div className="form_item">
<div className="form_input">
<span className="edit_profile_span">State</span>
<input type="text" name="locationState" placeholder="State" value={locationState} style={{ textTransform: "capitalize"}} onChange={this.handleChange.bind(this)}/>
<span className="bottom_border"></span>
</div>
</div>
</div>
<div className="form_row">
<div className="form_item">
<div className="form_input">
<span className="edit_profile_span">Country</span>
<input type="text" name="locationCountry" placeholder="Country" value={locationCountry} style={{ textTransform: "capitalize"}} onChange={this.handleChange.bind(this)}/>
<span className="bottom_border"></span>
</div>
</div>
</div>
<div className="form_row">
<div className="form_item">
<div className="form_input">
<span className="edit_profile_span">Interests</span>
<input type="text" name="interests" placeholder="Interests (e.g Sports, Wine, Outdoors ect.)" value={interests} style={{ textTransform: "capitalize"}} onChange={this.handleChange.bind(this)}/>
<span className="bottom_border"></span>
</div>
</div>
</div>
<div className="form_buttons">
<button type="submit" className="btn">
Save changes</button>
</div>
</div>
</form>
);
}}
</Mutation>
</Fragment>
)
}
}
export default withRouter(EditOtherProfileMutations);
I think the problem is that your mutation input fields are not the same as those defined in your schema.
Your schema has:
editOtherProfileDetails(
email: String!,
locationCity: String!,
locationState: String!,
locationCountry: String!,
interests: String!
): User
And you defined your mutation as follows:
mutation($locationCountry: String!){ ... }
The input params must match, so I think it would work if you define your mutation like this:
mutation NameOfYourMutation(
$email: String!,
$locationCity: String!,
$locationState: String!,
$locationCountry: String!,
$interests: String!
) { ... }
Also, as you might anticipate, this will slowly become hard to maintain.
I recommend having a look at input objects.
look
you are declaring mutation that take one argument and in resolver, it using email, locationCity, locationState, locationCountry, interests this args but not declare it will cause the problem you should be you are used the $locationCity and other but it doesn't datafiles should be take as argument
as this shape
mutation($locationCountry: String!
,$locationCity: String!,
$locationState: String!,
$locationCountry: String!,
$interests: String!){
editOtherProfileDetails(email: $email, locationCity: $locationCity, locationState: $locationState, locationCountry: $locationCountry, interests: $interests){
email
locationCity
locationState
locationCountry
interests
}
tell me in commit if it works or not
I figured out that I had made a mistake. Instead of:
const user = await User.findOneAndUpdate({ email },
{ $set: { locationCity: locationCity } },
{ $set: { locationState: locationState } },
{ $set: { locationCountry: locationCountry } },
{ $set: { interests: interests } },
{ new: true }
);
I needed to put:
const user = await User.findOneAndUpdate({ email },
{ $set: { locationCity: locationCity, locationState: locationState, locationCountry: locationCountry, interests: interests } },
{ new: true }
);
I'm new to graphql
I have a simple react app that lists books using a graphql query that queries a mongoDB database.
The schema contains a addBook Mutation that adds books to the DB.
This works using graphiql and I can add books and display them.
My problem now is I'm trying to use this mutation to add the books from a form on the react page.
I have a addBook component and listBooks component.
I get the error TypeError: this.props.addBookMutation is not a function
addBooks.js
import React, { Component } from 'react';
import { graphql } from 'react-apollo';
import { addBookMutation } from '../queries/queries';
class AddBooks extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
genre: "",
author: "",
}
}
submitForm(e) {
e.preventDefault()
this.props.addBookMutation({
variables: {
name: this.state.name,
genre: this.state.genre,
author: this.state.author,
}
})
}
render() {
return (
<div className="wrapper">
<form action="" className="o-form" onSubmit={this.submitForm.bind(this)}>
<div className="o-form__element">
<label className="o-form__label" htmlFor="">Book Name</label>
<input className="o-form__input" type="text" onChange={(e) => this.setState({ name: e.target.value })} />
</div>
<div className="o-form__element">
<label className="o-form__label" htmlFor="">Description</label>
<textarea className="o-form__input" type="text" onChange={(e) => this.setState({ genre: e.target.value })}>
</textarea>
</div>
<div className="o-form__element">
<label className="o-form__label" htmlFor="">Year</label>
<input className="o-form__input" type="text" onChange={(e) => this.setState({ author: e.target.value })} />
</div>
<button className="o-form__btn">Add Book</button>
</form>
</div>
)
}
}
export default graphql(addBookMutation)(AddBooks)
queries.js
import { gql } from 'apollo-boost';
const getBookQuery = gql`
{
fonts{
name
genre
author
}
}
`
const addBookMutation = gql`
mutation($name: String!, $genre: String!, $author: String!){
addBook(
name: $name,
genre: $genre,
author: $author
)
}
`
export { getBookQuery, addBookMutation };
you can't call this.props.addBookMutation, in your case for a class component call it by this.props.mutate({}) for more info
submitForm(e) {
e.preventDefault();
this.props.mutate({
variables: {
name: this.state.name,
genre: this.state.genre,
author: this.state.author,
}
}).catch(res => {
const errors = res.graphQLErrors.map(err => err.message);
this.setState({ errors });
});
}
I got an issue may cause from react-boilerplate Or "redux-form/immutable", wish someone can help me out.
I tried to put some custom props into Form component and this will print out messages of error when submit.
Here is my code:
import React from 'react';
import { Form, Icon } from 'semantic-ui-react';
import { PropTypes } from 'prop-types';
import { Field, reduxForm, reset } from 'redux-form/immutable';
import { connect } from 'react-redux';
import { ReduxFormInput, ReduxFormCheckbox } from '../../components/ReduxFormInput';
import { signupSync, passStrength } from '../../components/Validate';
import StyledButton from '../../components/StyledButton';
import AcceptTerms from './acceptTerms';
import signupRequest from './actions';
class Signup extends React.Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
signupRequest: PropTypes.func,
signup: PropTypes.shape({
requesting: PropTypes.bool,
successful: PropTypes.bool,
messages: PropTypes.array,
errors: PropTypes.array,
}),
}
submit(values, dispatch) {
console.log(values);
this.props.signupRequest(values); // will be undefined 'props' after submit
}
render() {
const {
handleSubmit,
submitting,
signup: {
requesting,
successful,
messages,
errors,
},
} = this.props;
return (
<Form onSubmit={handleSubmit(this.submit)} >
<Form.Field>
<Field
type="text"
name="accountName"
component={ReduxFormInput}
icon="user outline"
label="Tên tài khoản"
placeholder="Tên tài khoản của bạn"
/>
</Form.Field>
<Form.Field >
<Field
type="email"
name="email"
component={ReduxFormInput}
icon="mail outline"
label="Email"
placeholder="Email của bạn"
/>
</Form.Field>
<Form.Field required >
<Field
type="password"
name="password"
component={ReduxFormInput}
icon="lock"
label="Mật khẩu"
placeholder="Nhập mật khẩu"
warn={passStrength}
/>
</Form.Field>
<Form.Field required >
<Field
type="password"
name="confirmPassword"
component={ReduxFormInput}
icon="lock"
label="Xác nhận Mật khẩu"
placeholder="Xác nhận lại mật khẩu"
/>
</Form.Field>
<Form.Field>
<Field
defaultChecked
type="checkbox"
name="confirm"
checkboxLabel="Tôi muốn nhận thông tin thông qua email, SMS, hoặc điện thoại."
component={ReduxFormCheckbox}
/>
</Form.Field>
{AcceptTerms}
<div>
<StyledButton primary fluid type="submit" disabled={submitting} >
<Icon name="add user" />
Đăng ký tài khoản
</StyledButton>
</div>
</Form>
);
}
}
const mapStateToProps = (state) => ({
signup: state.signup,
});
const connected = connect(mapStateToProps, { signupRequest })(Signup);
const formed = reduxForm({
form: 'signup',
validate: signupSync,
onSubmitSuccess: afterSubmit,
})(connected);
const afterSubmit = (result, dispatch) => dispatch(reset('signup'));
export default formed;
My reducer
import { SubmissionError } from 'redux-form/immutable';
import {
SIGNUP_REQUESTING,
SIGNUP_SUCCESS,
SIGNUP_ERROR,
} from './constants';
const initialState = {
requesting: false,
successful: false,
errors: [],
messages: [],
};
const reducer = function signupReducer(state = initialState, action) {
switch (action.type) {
case SIGNUP_REQUESTING:
return {
requesting: true,
successful: false,
errors: [],
messages: [{
body: 'Signing up...',
time: new Date(),
}],
};
case SIGNUP_SUCCESS:
return {
requesting: false,
successful: true,
errors: [],
messages: [{
body: `Successfully created account for ${action.response.email}`,
time: new Date(),
}],
};
case SIGNUP_ERROR:
return {
requesting: false,
successful: false,
messages: [],
errors: new SubmissionError({
email: 'failed',
_error: 'failed',
}),
};
default:
return state;
}
};
export default reducer;
Inject reducer on routes.js
...
{
path: '/signup',
name: 'signup',
getComponent(nextState, cb) {
const importModules = Promise.all([
import('containers/SignupPage/reducer'),
import('containers/SignupPage/sagas'),
import('containers/SignupPage'),
]);
const renderRoute = loadModule(cb);
importModules.then(([reducer, sagas, component]) => {
injectReducer('signup', reducer.default);
injectSagas(sagas.default);
renderRoute(component);
});
},
}
...
Then I got an error screen like this.
TypeError: Cannot read property 'requesting' of undefined
Signup.render
/Users/son/Desktop/we-mak/app/containers/SignupPage/signupForm.js
Signup.tryRender
http://localhost:3000/main.js:1388:1
Signup.proxiedMethod
http://localhost:3000/main.js:1356:1
eval
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:796:21
measureLifeCyclePerf
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:75:12
ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:795:25
ReactCompositeComponentWrapper._renderValidatedComponent
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:822:32
ReactCompositeComponentWrapper._updateRenderedComponent
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:746:36
ReactCompositeComponentWrapper._performComponentUpdate
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:724:10
ReactCompositeComponentWrapper.updateComponent
webpack:///./~/react-dom/lib/ReactCompositeComponent.js?:645:12
I notice that react-boilerplate doesn't use react-hot-loader so I guessed it may cause from boilerplate, but I don't have enough webpack experience to config it.
This error message means your signup property is undefined, which may happen if your state does not have signup property or that property is undefined. Have a look at your reducer.