Problem beim Senden einer POST-Anfrage mit Axios in Reactjs
Hallo allerseits, ich verwende Reactjs und Redux für das Frontend und möchte neue Artikel erstellen, also habe ich CreateArticle.js wie folgt erstellt
import { useDispatch, useSelector } from 'react-redux'
import { unwrapResult } from '@reduxjs/toolkit'
import { addNewArticle } from './managementSlice'
import { selectAccessToken, selectUser } from '../authentications/authenticationsSlice'
import './CreateArticle.scss';
import { selectAllSubjects, fetchSubjects } from '../subjects/subjectsSlice';
import { selectAllTags, fetchTags } from '../tags/tagsSlice';
export const CreateArticle = () => {
const [title, setTitle] = useState('')
const [body, setBody] = useState('')
const [slug, setSlug] = useState('')
const [subjectId, setSubjectId] = useState(0)
const [tags, setTags] = useState([])
const [addRequestStatus, setAddRequestStatus] = useState('idle')
const user = useSelector(selectUser);
const subjects = useSelector(selectAllSubjects)
const allTags = useSelector(selectAllTags)
const subjectStatus = useSelector((state) => state.subjects.status)
const tagStatus = useSelector( (state) => state.tags.status)
const dispatch = useDispatch()
// const onSubjectChanged = (e) => setSubjectId(parseInt(e.target.value))
const onSubjectChanged = (e) => setSubjectId(e.target.value)
const onTitleChanged = (e) => {
setTitle(e.target.value)
setSlug(e.target.value.toLowerCase())}
const onBodyChanged = (e) => {
setBody(e.target.value)
console.log(e.target.value);
}
const onTagsChanged = (e) => {
const selectedOptions = [...e.target.selectedOptions].map(o => parseInt(o.value))
setTags(selectedOptions)
}
const onSaveArticleClicked = async () => {
let article = { Subject:subjectId, Title: title, Body:body, Tags:tags, Slug:slug }
if (user){
try {
setAddRequestStatus('pending')
console.log('addRequestStatus:', addRequestStatus)
const resultAction = await dispatch(
addNewArticle(article)
)
unwrapResult(resultAction)
setTitle('')
setBody('')
setTags([])
setSlug('')
console.log('resultAction:', resultAction)
} catch (err) {
console.error('Failed to save the article: ', err)
} finally {
setAddRequestStatus('idle')
}
}
}
useEffect( () =>
{
if (subjectStatus === 'idle') {
dispatch(fetchSubjects())
}
},
[subjectStatus, dispatch]
)
let subjectsOptions
if (subjectStatus === 'loading') {
subjectsOptions = <div className="loader"> Loading... </div>
} else if (subjectStatus === 'succeeded') {
subjectsOptions = subjects.map((subject) => (
<option key={subject.id} value={subject.id} >
{subject.title}
</option>
))
} else if (subjectStatus === 'error') {
subjectsOptions = <div> Something went wrong </div>
}
useEffect( () =>
{
if (tagStatus === 'idle') {
dispatch(fetchTags())
}
},
[tagStatus, dispatch]
)
let tagsOptions
if (tagStatus === 'loading') {
tagsOptions = <div className="loader"> Loading... </div>
} else if (tagStatus === 'succeeded') {
tagsOptions = allTags.map((tag) => (
<option key={tag.id} value={tag.id} >
{tag.title}
</option>
))
} else if (tagStatus === 'error') {
tagsOptions = <div> error </div>
}
return (
<div className="create-article">
<div className="create-article-head">
</div>
<form className="create-article-form" >
<label htmlFor="article-title">Article Title:</label>
<input
type="text"
className="article-title-input"
id="id-article-title-input"
name="title"
placeholder="What's on your mind?"
value={title}
onChange={onTitleChanged}
/>
<label htmlFor="article-subject">subject:</label>
<select
id="id-subjects-article-select"
className="subjects-article-select"
onChange={onSubjectChanged}>
<option value="">
انتخاب موضوع
</option>
{subjectsOptions}
</select>
<label htmlFor="article-tags">tags:</label>
<select
id="id-tags-article-select"
className="tags-article-select"
onChange={onTagsChanged}
multiple
>
<option value="">
SELECT TAGS
</option>
{tagsOptions}
</select>
<label htmlFor="article-body">Body:</label>
<textarea
className="article-body-textarea"
id="id-article-body-textarea"
name="body"
value={body}
onChange={onBodyChanged}
/>
<button
type="button"
onClick={onSaveArticleClicked}
>
Save Article
</button>
</form>
</div>
)
}
Dann habe ich managementSlice.js erstellt, um Daten wie folgt an den Server zu senden:
import {
createSlice,
createAsyncThunk,
createEntityAdapter,
} from '@reduxjs/toolkit'
// import axios from 'axios';
// with below import axios workes correctly
import * as axios from 'axios';
const managementAdapter = createEntityAdapter()
const initialState = managementAdapter.getInitialState({
status: 'idle',
error: null,
})
export const fetchMyArticles = createAsyncThunk('myArticles/fetchMyArticles', async () => {
// const accessToken = useSelector(selectAccessToken);
const accessToken = localStorage.getItem('access_token')
const ARTICLES_PATH = 'http://127.0.0.1:8000/articles_api/v1/management/';
const response = await axios(ARTICLES_PATH,
{ headers: { "Authorization": `Bearer ${accessToken}` }}) const data = response; console.log( 'fetchMyArticles: ', data) return response.data }) export const addNewArticle = createAsyncThunk( 'management/addNewArticle', async (initialArticle) => { const accessToken = localStorage.getItem('access_token') const ARTICLE_CREATE_PATH = 'http://127.0.0.1:8000/articles_api/v1/management/'; console.log("before send new article to server:", initialArticle) try { const response = await axios.post(ARTICLE_CREATE_PATH, initialArticle , { headers: { "Authorization": `Bearer ${accessToken}`,
'Content-Type' : 'application/json; charset=UTF-8',
}})
console.log('what the hell:', response);
} catch (error) {
console.error('erroroo',error.response.data);
}
}
)
const managementSlice = createSlice({
name: 'management',
initialState,
reducers: {},
extraReducers: {
[fetchMyArticles.pending]: (state, action) => {
state.status = 'loading'
},
[fetchMyArticles.fulfilled]: (state, action) => {
state.status = 'succeeded'
// Add any fetched articles to the array
managementAdapter.upsertMany(state, action.payload)
},
[fetchMyArticles.rejected]: (state, action) => {
state.status = 'failed'
state.error = action.payload
},
[addNewArticle.fulfilled]: managementAdapter.addOne,
},
})
export const {
} = managementSlice.actions
export default managementSlice.reducer
export const {
selectAll: selectMyArticles,
selectById: selectMyArticleById,
selectIds: selectMyArticleIds,
} = managementAdapter.getSelectors((state) => state.management)
aber nach dem Senden der Anfrage erhalte ich 400 fehlerhafte Anfrage Fehler. Ich verstehe nicht, welchen Teil ich falsch mache? Mein Backend ist bei Django und ich habe es mit dem Postboten getestet. Es ist in Ordnung, wenn ich Daten mit dem Postboten sende
Antworten
Ich hatte das gleiche Problem mit der .NET-Web-API. Es wäre ein Axios Request Header / Body Problem. Sie sollten die Überschriften Ihrer Post-Anfrage wie folgt festlegen:
headers: {
'content-type': 'application/json',
}
Oder versuchen Sie, den Anfragetext als Formulardaten zu senden als:
let formData = new FormData()
formdata.append('name', yourJson)
await axios({
method: 'post',
url: '/your/url',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
})