Problem beim Senden einer POST-Anfrage mit Axios in Reactjs

Sep 29 2020

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

1 DevLoverUmar Sep 29 2020 at 08:48

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',
  },
})