complete code example at the end.
Got this problem when post data with React/Next js.
The most possible reason you get this error is the fetch() haven't get the right response.
Based on my case, the problem happened because of the url path.
make sure your fectch url is right. here is a wrong example of using relative path:
fetch('/blogs/',options)
.then(res => {
console.log(res) // only for debugging
return res.json()
})
.then(response => console.log(`response`,response))
.catch(error => console.log(`error`,error))
make a post and get result:
Response {
type: "basic",
url: "http://localhost:3000/blogs",
redirected: true,
status: 200,
ok: true,
statusText: "OK",
headers: Headers,
body: ReadableStream, bodyUsed: false
}
error SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Haha! we got status code 200
and ok
is true
. But what it means is actually a get
success:
200
: get success201
: post success where is the problem? look at the url:
http://localhost:3000/blogs
!http://127.0.0.1:8000
so instead of using relative path, we should use the absolute path of our REST API.
fetch('http://127.0.0.1:8000/blogs/',options)
.then(...)
note in the above we use domain/blogs/
rather than domain/blogs
.
if you use fetch url without a trailling slash, you can not get right response either, but this error is easy to be found since you will get an error in the backend:
RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redi
rect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/blogs/ (note the trailing slash)
, or set APPEND_SLASH=False in your Django settings.
as it suggests,
/
to your pathAPPEND_SLASH=False
in your settingsThis is also a point we'ed know when debugging.
const Post = () => {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const submitPost = async (event) => {
event.preventDefault();
const options = {
method:"POST",
body:JSON.stringify({
title: title,
description: description
}),
headers:{
"Content-Type":"application/json"
},
}
fetch('http://127.0.0.1:8000/tools/',options)
.then(res => {
console.log(res)
return res.json()
})
.then(response => console.log(`response`,response))
.catch(error => console.log(`error`,error))
}
return (
<form className={styles.postForm}
onSubmit={submitPost}>
{/*<CSRFToken />*/}
<p>
<label htmlFor="title">Title</label>
<input
id="title"
name="title"
type="text"
autoComplete="name"
required
onChange = {(e) => setTitle(e.target.value)}
/>
</p>
<p>
<label htmlFor="description">Description</label>
<textarea
id="description"
name="description"
onChange={(e) => setDescription(e.target.value)}
>
</textarea>
</p>
<button className={styles.postSubmit} type="submit">submit</button>
</form>
)
}
export default Post
success response example:
Response { type: "cors", url: "http://127.0.0.1:8000/tools/", redirected: false, status: 201, ok: true, statusText: "Created", headers: Headers, body: ReadableStream, bodyUsed: false }
post.js:25:20
response: Object { id: 6, title: "post example", description: "this is the content", created_at: "2022-01-30T20:14:04.337325Z", updated_at: "2022-01-30T20:14:04.337325Z" }
note the url(http://127.0.0.1:8000/blogs/
) and status code (201
).