Reputation: 175
Good afternoon
I am a newbie. Want to make a CRUD using reacts,redux-thunk, axios, json-server.
but I've found hard to stick in one correct way to deal with actions
I have this reducer:
import { types } from "../types/types";
const initialState = {
data: null,
deleted: null,
error: ''
}
export const axiosDataReducer = (state = initialState, action) => {
switch (action.type) {
case types.get:
return {
...state,
data: action.data
}
case types.delete:
return {
...state,
deleted: action.deletedItem
}
case types.error:
return {
...state,
error: action.msg
}
default:
return state;
}
}
I have this actions:
import axios from "axios";
import { baseURL } from "../json-server/baseURL"
import { types } from '../types/types'
// get data
export const fetchData = () => {
return (dispatch) => {
return axios.get(baseURL)
.then(response => {
return response.data
})
.then(data => {
dispatch({
type: types.get,
data: data
})
})
.catch(error => dispatch(
{
type: types.error,
msg: "Unable to fetch data"
}));
};
};
//delete data
export const deleteData = (id) => {
return (dispatch) => {
return axios.get(`${baseURL}${id}`)
.then(response => {
return response.data
})
.then(data => {
console.log(data)
dispatch({
type: types.error,
deletedItem: data
})
})
.catch(error => dispatch(
{
type: types.error,
msg: "Unable to delete data"
}));
};
};
I have this (Table component) component in which I use a dispatch inside a useEffect and works, I get the data and I render the data inside my table, but I don t know why is working like that, isn t a double dispatch inside the useEffect?:
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { fetchData } from '../actions/actions';
import ButtonCreate from './buttons/ButtonCreate';
import ButtonDelete from './buttons/ButtonDelete';
import ButtonUpdate from './buttons/ButtonUpdate';
export default function Tabla() {
const dispatch = useDispatch()
const { data } = useSelector(state => state.axiosDataReducer)
useEffect(() => {
dispatch(fetchData())
}, [])
return (
<div className='container mt-5 mb-5'>
<ButtonCreate />
<table className="table table-striped table-hover caption-top ">
<caption>Online Store</caption>
<thead className='table-dark'>
<tr className='text-center'>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Cost</th>
<th scope="col">Category</th>
<th scope="col">Department</th>
<th scope="col">Update</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{
data?.map((x, index) => (
<tr key={x.id}>
<th scope="col">{index + 1}</th>
<th scope="col">{x.name}</th>
<th scope="col">$ {x.cost.toFixed(2)}</th>
<th className='text-center'>
{
x.category.map((y, index) => (
<span key={index * 0.125}>{y.name}</span>
))
}
</th>
<th className='text-center'>
{
x.department.map((z, index) => (
<span key={index * 0.225}>{z.name}</span>
))
}
</th>
<th><ButtonUpdate /></th>
<th><ButtonDelete id={x.id} /></th>
</tr>
))
}
</tbody>
</table>
</div>
)
}
and in the same Table component, I want to click the delete button:
import React from 'react'
import { deleteData } from '../../actions/actions'
export default function ButtonDelete({ id }) {
return (
<div>
<button
className='btn btn-danger'
onClick={deleteData(id)}
>
Delete
</button>
</div>
)
}
, but now, for this previous example, it just will dispatch the element I am pointing to, the console.log works fine, but if I try to dispatch I obtain this error:
Unhandled Rejection (TypeError): dispatch is not a function
Uncaught (in promise) TypeError: dispatch is not a function
What does this means?
I want to find out the most basic way of doing this asyc request to server using actions. I don t know why is dispatching not working properly.
thanks in advance, I apreciate it
Upvotes: 0
Views: 299
Reputation: 390
You have a typo in your deleteData()
function . I believe you should use types.delete
in your dispatch type instead of types.error
.
Also, in your Table
component, you must use useDispatch
as well. Because, this hook returns a reference to the dispatch
function from the Redux store that must be passed to deleteData
. And your onClick
event should have a function that returns a dispatch. Something like this maybe:
<button
className='btn btn-danger'
onClick={() => dispatch(deleteData(id))}
>
You might want to check docs as well.
Upvotes: 1