Skip to content
Advertisement

Uncomplete payload | React & Redux Toolkit

I have a big problem,maybe it’s not so big but i dont sleep for almost 24h because of it.I barely finished this Slice,but now,when i submit the data,i get only the automatically set id..
So,to be clear.I have a skill component where i have 2 input forms and a button,i need to retrieve data from both inputs,and then,when they are being submited,to be fetched and saved in persistor. Till now everything is good,i introduce data,the post request is successeful,but,the payload is only with the id that mirage js generates automatically.But i need to have an array with Type,Range props and with their values,and everytime i click on the button the array of this objects should be populated.
This is my component:
enter image description here
Here i submit data:
enter image description here

And as you can see,only the id is present there.. I’m stucked…
enter image description here

And above is the list when i submited data 6 times.. only the id,i dont know what may be the problem,please help..
Skill component:

import React, { useState,useEffect } from 'react'
import { Formik, Form, useFormik } from 'formik'
import * as Yup from 'yup'
import FormikControl from '../Form/FormikControl'
import DisplayFormikState from '../Form/DisplayFormikState.js'
import { useDispatch, useSelector } from 'react-redux'
import { addNewSkill,fetchSkills,selectSkill } from '../../features/skills/skillSlice'

const Skills = () =>{
    const dispatch = useDispatch();
    // const [skill, setSkills] = useState({
    //     name: '',
    //     range: null
    //   });

      useEffect(()=>{
        dispatch(fetchSkills());
        },[dispatch])

    //   const userInfo = useSelector(selectSkill);
    //   const skillList = useSelector(state => state.skillState.skills)
    //   console.log('skillList',skillList)
     const { status, error } = useSelector(state => state.skills)
// console.log(status)
// console.log(error)
const [type,setType] = useState('')
const [range,setRange] =useState('')

const handleAction = (e) => {
e.preventDefault()
      dispatch(addNewSkill(type));
      dispatch(addNewSkill(range));
      setType('');
      setRange('');
    }
  
    //   const handleChange = (e) => {
    //     const { name, value } = e.target;
    //     setSkills({ ...skill, [name]: value });
    //   };
    
    //   const handleSubmit = (e) => {
    //     e.preventDefault();
    //     dispatch(addNewSkill(skill));
    //   };


    //   import { useSelector } from "react-redux";

// As you see we're getting the whole state
// but we're only returning list which is the 
// name we gave it in the reducers file
const list = useSelector(state => state.list);


    const formik = useFormik({
        // initialValues:{
        //     name: skill.name,
        //     range: skill.range
        // },
        validationSchema:Yup.object({

        }),
        
    })

    

    return(
        <>
        <section id="skills">
        <h1 className='SkillSection'>Skills</h1>
        <form>
        <div>
        <label htmlFor="type">Type</label>
<input 
id='type'
name='name'
type='text'
placeholder='Enter skill name'
value={type}
onChange={(e)=>setType(e.target.value)}
// value={formik.values.name}
/>
</div>

<div>
<label htmlFor="level">Level</label>
    <input 
    id='level'
    type='text'
    name='range'
    placeholder='Enter range'
    value={range}
    onChange={(e)=>setRange(e.target.value)}
    // value={formik.values.range}
    />
</div>
<button type='submit' onClick={handleAction}>Submit</button>
</form>
        </section>
        </>
    )
}

export default Skills  

Slicer:

export const fetchSkills = createAsyncThunk(
    'skills/fetchSkills',
    async (_, {rejectWithValue}) => {
       try{
           const response = await fetch('/api/skills',{
               method:'GET',
           })
//  console.log(response)
           if(!response.ok){
               throw new Error ('Server Error!');
           }

           const data = await response.json();
// console.log(data)
           return data;
       } catch(error){
           return rejectWithValue(error.message);
       }
    }
    );

    const setError = (state, action) => {
        state.status = 'rejected';
        state.error = action.payload;
    }

    
export const addNewSkill = createAsyncThunk(
    'skills/addNewSkill',
    async (skillData,{rejectWithValue,dispatch}) =>{
        const {skillName,skillRange} = skillData
try{
const skill = {
    name: skillName,
    range: skillRange,
};
const response = await fetch('/api/skills',{
    method:'POST',
    headers:{
        'Content-name' : 'application/json',
    },
    body: JSON.stringify(skill)
});

if(!response.ok){
    throw new Error('Can't add skill. Server error')
}

const data = await response.json();

dispatch(setSkill(data))

}catch(error){
return rejectWithValue(error.message);
}
    }
)


export const skillSlice = createSlice({
  name: "skills",
  initialState: {
    skills:[],
    status: null,
    error: null
  },
  reducers: {
    setSkill: (state, action) => {
    //   console.log("action", action.payload);
    //   state.name = action.payload?.name;
    //   state.range = action.payload?.range;
    state.skills.push(action.payload);
//  localStorage.setItem(state.name,action.payload.range)
    },
  },
  extraReducers:{
      [fetchSkills.pending]:(state,action)=>{
        state.status = 'loading';
        state.error = null;
      },
      [fetchSkills.fulfilled]:(state,action)=>{
        state.status = 'resolved';
        state.name = action.payload;
      },
      [fetchSkills.rejected]: setError,
  }
});


 const { setSkill } = skillSlice.actions;

export const selectSkill = (state) => state?.skill;

export default skillSlice.reducer;

Miragejs server where i mock the apis:

import { createServer,Model } from "miragejs"

export const makeServer =({ environment = 'test' } = {})  => {
    let server = createServer({
      environment,
        models: {
          educations: Model,
         skills:Model
        },

        seeds(server) {
            server.create("education", { date: 2001, title: "Title 0", text: "Elit voluptate ad nostrud laboris. Elit incididunt mollit enim enim id id laboris dolore et et mollit. Mollit adipisicing ullamco exercitation ullamco proident aute enim nisi. Dolore eu fugiat consectetur nulla sunt Lorem ex ad. Anim eiusmod do tempor fugiat minim do aliqua amet ex dolore velit.rn" });
            server.create("education", { date: 2000, title: "Title 1", text: "Et irure culpa ad proident labore excepteur elit dolore. Quis commodo elit culpa eiusmod dolor proident non commodo excepteur aute duis duis eu fugiat. Eu duis occaecat nulla eiusmod non esse cillum est aute elit amet cillum commodo.rn" });
            server.create("education", { date: 2012, title: "Title 2", text: "Labore esse tempor nisi non mollit enim elit ullamco veniam elit duis nostrud. Enim pariatur ullamco dolor eu sunt ad velit aute eiusmod aliquip voluptate. Velit magna labore eiusmod eiusmod labore amet eiusmod. In duis eiusmod commodo duis. Exercitation Lorem sint do aliquip veniam duis elit quis culpa irure quis nulla. Reprehenderit fugiat amet sint commodo ex.rn" });
          },
    
        routes() {
            //this.namespace = 'api/educations';
            this.get('api/educations', (schema, request) => {
              return schema.educations.all();
            },
            { timing: 1000 });

            // this.namespace = 'api/skills';
            this.get('api/skills', (schema, request) => {
              return schema.skills.all();
            },
            { timing: 1000 });
    

          this.post('api/skills', (schema, request) => {
            let attrs = JSON.parse(request.requestBody);
            return schema.skills.create(attrs);
          },
          { timing: 1000 });
        },
      })
      return server;
    }  

And root reducer:

const rootReducer = combineReducers({
    visibilityState: toggleButtonReducer,
    educationState: educationReducer,
    skills : skillReducer
})

Advertisement

Answer

You are dispatching addNewSkill with a string value whereas you are expecting an object in thunk middleware.

dispatch(addNewSkill(type));
dispatch(addNewSkill(range));

export const addNewSkill = createAsyncThunk(
    'skills/addNewSkill',
    async (skillData,{rejectWithValue,dispatch}) =>{
    const {skillName,skillRange} = skillData
    // skillData is not an object but a string
})

You should replace your handleAction with this.

const handleAction = (e) => {
    e.preventDefault()
    dispatch(addNewSkill({skillName: type, skillRange: range}));
    setType('');
    setRange('');
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement