'GraphQL + ReactJS throws Error 400: Bad Request

I've been stuck at trying to submit my form for a couple of days now. I constantly get hit with the following error: "POST http://localhost:5000/graphql 400 (Bad Request)".

I believe the problem lies somewhere within the mutation/query itself and not the headers since the request is sent in the correct content type (application/json) as you can see in the screenshot.enter image description here

My code (warning, I'm an absolute beginner) is the following:

// @flow
import React, { useState } from 'react';
import { Row, Col, Card, OverlayTrigger, Tooltip } from 'react-bootstrap';
import { FormInput } from '../../../../components';




type ChecklistsItems = {
    id: number,
    title: string,
    completed: boolean,
};

type AttachmentsItems = {
    id: number,
    filename: string,
    size: string,
};

type CommentsItems = {
    id: number,
    author: string,
    text: string,
    posted_on: string,
    author_avatar: string,
};

type TaskProps = {
    id: number,
    title: string,
    assigned_to: string,
    assignee_avatar: string,
    due_date: string,
    completed: boolean,
    priority: string,
    stage: string,
    checklists: Array<ChecklistsItems>,
    description: string,
    attachments: Array<AttachmentsItems>,
    comments: Array<CommentsItems>,
};

const createMarkup = (text) => {
    return { __html: text };
};

const Task = (task: TaskProps): React$Element<React$FragmentType> => {
    const [completed, setCompleted] = useState(task.completed == true);
    const [enteredTitle, setEnteredTitle] = useState('');
    const [enteredPriority, setEnteredPriority] = useState('');
    const [enteredDescription, setEnteredDescription] = useState('');
    const [enteredDeadline, setEnteredDeadline] = useState('');
    const [enteredStartTime ,setEnteredStartTime] = useState('');
    const [enteredEndTime, setEnteredEndTime] = useState('');
    const [enteredColor, setEnteredColor] = useState('');


    

    /*
     * mark completd on selected task
     */
    const markCompleted = (e) => setCompleted(e.target.checked);

    const titleChangeHandler = (event) => {
        setEnteredTitle(event.target.value);

    };

    const  priorityChangeHandler = (event) => {
        setEnteredPriority(event.target.value);
    };

    const descriptionChangeHandler = (event) => {
        setEnteredDescription(event.target.value)
    };

    const deadlineChangeHandler = (event) => {
        setEnteredDeadline(event.target.value)
    }

    const startTimeChangeHandler = (event) => {
        setEnteredStartTime(event.target.value);
    }

    const endTimeChangeHandler = (event) => {
        setEnteredEndTime(event.target.value);
    }

    const colorChangeHandler = (event) => {
        setEnteredColor(event.target.value);
    }

    const submitHandler = (event) => {
        event.preventDefault();
     
     
        const taskData = {
            title: enteredTitle,
            priority: enteredPriority,
            description: enteredDescription,
            due_date: new Date(enteredDeadline),
            start: new Date(enteredStartTime),
            end: new Date(enteredEndTime),
            color: enteredColor,
        };

        console.log(taskData);
        setEnteredTitle('');
        setEnteredPriority('');
        setEnteredDescription('');
        setEnteredDeadline('');
        setEnteredStartTime('');
        setEnteredEndTime('');
        setEnteredColor('#');
    

        const requestBody = {
            query: `
                mutation {
                    createTask(taskInput: {title: "${enteredTitle}", description: "${enteredPriority}", priority: "${enteredDescription}", due_date: "${enteredDeadline}", start: "${enteredStartTime}", end: "${enteredEndTime}", color: "${enteredColor}"} ) {
                        _id
                        title
                        description
                        priority
                        due_date
                        start
                        end
                        color
                        creator {
                            id
                            email
                        }
                    }
                }
            `
    };

    fetch('http://localhost:5000/graphql', {
        method: 'POST',
        body: JSON.stringify(requestBody),  
        headers: {
            'Content-Type': 'application/json'
        }
      })
        .then(res => {
          if (res.status !== 200 && res.status !== 201) {
            throw new Error('Failed!');
          }
          return res.json();
        })
        .then(resData => {
          this.fetchTasks();
        })
        .catch(err => {
          console.log(err);
        });
    
};

    return (
        <React.Fragment>
            <div style={{marginTop:'118px'}} />
            <Card >
                <Card.Body>
                   <h3>Add Task</h3>
                   <p style={{opacity: "70%"}}>You can add items in the form below. These tasks will automatically be added to your task list and your calendar.</p>
                    <hr className="mt-4 mb-2" />

                    <Col>
                    <Row className="mt-2">
                    <form className="p-2" onSubmit={submitHandler}>

<Row>
    <OverlayTrigger
        placement="top"
        overlay={<Tooltip>Enter a title/name for your task.</Tooltip>}>
    <Col md={8}>
        <FormInput
            name="title"
            label="Title"
            placeholder="Enter title"
            type="text"
            containerClass="mb-3"
            className="form-control form-control-light"
            key="title"
            value={enteredTitle}
            onChange={titleChangeHandler}
        />
    </Col>
    </OverlayTrigger>
    <OverlayTrigger
        placement="top"
        overlay={<Tooltip>Set a priority status to your task.</Tooltip>}>
    <Col md={4}>
        <FormInput
            name="priority"
            label="Priority"
            type="select"
            containerClass="mb-3"
            className="form-select form-control-light"
            key="priority"
            value={enteredPriority}
            onChange={priorityChangeHandler}
            >
            <option>Select</option>
            <option>Low</option>
            <option>Medium</option>
            <option>High</option>
        </FormInput>
    </Col>
    </OverlayTrigger>
</Row>
<OverlayTrigger
        placement="top"
        overlay={<Tooltip>Enter a description to explain details about the task.</Tooltip>}>
<Col>
<FormInput
    name="description"
    label="Description"
    type="textarea"
    containerClass="mb-3"
    className="form-control form-control-light"
    rows="3"
    key="description"
    value={enteredDescription}
    onChange={descriptionChangeHandler}
/>
</Col>
</OverlayTrigger>

        <OverlayTrigger
         placement="top"
         overlay={<Tooltip>Enter the date when the task has to be finished.</Tooltip>}>
         <div className="form-group">
             <FormInput
             name="dueDate"
             label="Due Date"
             type="date"
             value={enteredDeadline}
             onChange={deadlineChangeHandler}>     
             </FormInput>
           </div>
        </OverlayTrigger>

<br />
<Row>
    <OverlayTrigger
         placement="top"
         overlay={<Tooltip>Set a start time for your task. The task will be listed in your personal calendar accordingly.</Tooltip>}>
    <Col md={6}>
        <div className="form-group">
            <label className="form-label">Start time</label> <br />

            <FormInput 
            type="datetime-local"
            value={enteredStartTime}
            onChange={startTimeChangeHandler}
            />

        </div>
    </Col>
    </OverlayTrigger>

    <OverlayTrigger
         placement="top"
         overlay={<Tooltip>Set an end time for your task. The task will be listed in your personal calendar accordingly.</Tooltip>}>
    <Col md={6}>
        <div className="form-group">
            <label className="form-label">End time</label> <br />

            <FormInput 
            type="datetime-local"
            value={enteredEndTime}
            onChange={endTimeChangeHandler}
            />
            
        </div>
    </Col>
    </OverlayTrigger>

</Row>    
<br />                    
<Row>
<OverlayTrigger
         placement="top"
         overlay={<Tooltip>Set the color with which you want your task to appear in the calendar.</Tooltip>}>
    <Col md={6}>
        <div className="form-group">
            <label className="form-label">Color</label> <br />
            <FormInput 
            type="color"
            // value={enteredColor}
            onChange={colorChangeHandler}
            >

            </FormInput>
            {/* <CirclePicker /> */}
        </div>
    </Col>
    </OverlayTrigger>

</Row>
    
<Col>
                         <button style={{marginTop: '50px', marginLeft: "23%", width: "300px"}} type="submit" className="btn btn-sm btn-success">
                                                        <i className="uil uil-message me-1"></i>Add Task
                         </button>
                    </Col>

</form>
                    </Row>
                    </Col>
                    
                </Card.Body>
            </Card>
        </React.Fragment>
    );
};


export default Task;

Right now, I can submit and log the formdata to my console in the form of an object so I know the technique behind it works. However, I just can't seem to manage inserting it into my actual database.

If someone is able to help me out it would be wildly appreciated!

Kind regards,

Abbeneji



Solution 1:[1]

On the submitHandler, I can see that you have created a const taskData for managing your inputs, well!. you logged taskData on console seems fine on console as well, and again you set them empty and reusing that UseState const on request body, may they already set empty there. Also look at the payload data(Next after Headers tab) and compare it with the api request flow, which may helpful for you to debugging. There may be a chance of request payload formed incorrectly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hari Upreti