Reputation: 79
I have the error:
TypeError: dispatch is not a function
in this line of code dispatch(addNewNote(response.data.message));
I don't know why this error is happening, since I have other dispatches in other functions within the thunks.js file working just fine.
I really need help, any advice would be appreciated.
Please consider the code below:
binnacleReducer.js
import { ADD_NEW_NOTE } from "../Actions/binnacleActions";
export const binnacleNotesReducer = (state = [], action) => {
const { type, payload } = action;
switch (type) {
case ADD_NEW_NOTE:
const { binnacleNote } = payload;
return state.concat(binnacleNote);
default:
return state;
}
};
binnacleActions.js
//Action creators and actions
export const ADD_NEW_NOTE = "ADD_NEW_NOTE";
export const addNewNote = (binnacleNote) => ({
type: ADD_NEW_NOTE,
payload: {
binnacleNote,
},
});
thunks.js
import axios from "axios";
import { loginSuccess, loginFailed } from "../Actions/authActions";
import {
setOwnerSetup,
setSuperSetup,
loadBinnacleNotes,
binnacleNoteReview,
addNewNote,
} from "../Actions/binnacleActions";
export const addBinnacleNote = (
binnacle,
noteNumber,
binnacleNote,
responsible,
file
) => async (dispatch, getState) => {
try {
const bodyToSend = new FormData();
bodyToSend.append("binnacle", binnacle);
bodyToSend.append("binnacleNote", binnacleNote);
bodyToSend.append("noteNumber", noteNumber);
bodyToSend.append("responsible", responsible);
if (file) {
for (let x = 0; x < file.length; x++) {
bodyToSend.append(`file[${x}]`, file[x]);
}
}
const response = await axios.post(
"http://localhost:5000/addBinnacleNote",
bodyToSend,
{
headers: {
"Content-Type": "application/json",
},
}
);
dispatch(addNewNote(response.data.message));
} catch (e) {
alert("Thunk error in addNote: " + e);
}
};
EDIT:
BinnacleForm.js
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { addBinnacleNote } from "../../Store/Thunks/thunks";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import TextField from "@material-ui/core/TextField";
import Container from "@material-ui/core/Container";
import { Button } from "@material-ui/core";
import AccordionTest from "./AccordionTest";
var noteNumber;
function BinnacleForm({ authReducer, binnacleNotesReducer }) {
const [binnacleNote, setBinnacleNote] = useState(null);
const [file, setFile] = useState(null);
const responsible = authReducer.role;
const binnacle = authReducer.binnacle;
const setBinnacleId = () => {
if (binnacleNotesReducer !== [] || binnacleNotesReducer.length === 0) {
noteNumber = 1;
} else {
noteNumber = binnacleNotesReducer[binnacleNotesReducer.length - 1].id + 1;
}
};
setBinnacleId();
return (
<React.Fragment>
<Container maxWidth="md">
<Typography variant="h6" gutterBottom>
Agregar Nota
</Typography>
{/* <AccordionTest /> */}
<Grid container spacing={3}>
<Grid item xs={12} sm={9}>
<TextField
required
id="binnacle_note"
name="binnacle_note"
fullWidth
autoComplete="given-name"
helperText="Nota"
onChange={(e) => setBinnacleNote(e.target.value)}
/>
</Grid>
<Grid item xs={12} sm={3}>
<Button variant="contained" component="label">
Adjuntar Archivo
<input
onChange={(e) => setFile(e.target.files)}
type="file"
hidden
multiple
/>
</Button>
</Grid>
<Button
variant="contained"
color="primary"
onClick={addBinnacleNote(
binnacle,
noteNumber,
binnacleNote,
responsible,
file
)}
>
Agregar Nota
</Button>
</Grid>
</Container>
</React.Fragment>
);
}
const mapStateToProps = (state) => ({
binnacleReducer: state.binnacleReducer,
authReducer: state.authReducer,
binnacleNotesReducer: state.binnacleNotesReducer.binnacleNotes,
});
const mapDispatchToProps = (dispatch) => ({
addBinnacleNote: (binnacle, binnacleNote, responsible) =>
dispatch(addBinnacleNote(binnacle, binnacleNote, responsible)),
});
export default connect(mapStateToProps, mapDispatchToProps)(BinnacleForm);
EDIT 2:
BinnacleForm.js
import React, { useEffect } from "react";
import { connect } from "react-redux";
import SetupBinnacleSuper from "../Binnacle/SetupBinnacleSuper";
import SetupBinnacleOwner from "../Binnacle/SetupBinnacleOwner";
import {
getBinnacleStatus,
getBinnacleStatusBySuper,
} from "../../Store/Thunks/thunks";
import BinnacleNotesList from "../Binnacle/BinnacleNotesList";
const Binnacle = ({
authReducer,
binnacleReducer,
getBinnacleStatus,
getBinnacleStatusBySuper,
}) => {
const binnacle = authReducer.binnacle;
const renderConditionaly = () => {
if (authReducer.role == "owner" && binnacleReducer.binnacleIsActive == 0) {
return <SetupBinnacleOwner />;
} else if (
authReducer.role == "owner" &&
binnacleReducer.binnacleIsActive == 1
) {
console.log("If Owner");
return <div>Owner</div>;
} else if (
authReducer.role == "super" &&
binnacleReducer.binnacleIsActiveBySuper == 0
) {
return <SetupBinnacleSuper />;
} else if (
authReducer.role == "super" &&
binnacleReducer.binnacleIsActiveBySuper == 1
) {
return <BinnacleNotesList />;
} else if (authReducer.role == "dro") {
return <BinnacleNotesList />;
} else if (authReducer.role == "constructor") {
return <BinnacleNotesList />;
}
};
useEffect(() => {
getBinnacleStatus(binnacle);
getBinnacleStatusBySuper(binnacle);
}, []);
return (
<div>
<h2>Bienvenido {authReducer.email}</h2>
{renderConditionaly()}
</div>
);
};
const mapStateToProps = (state) => ({
authReducer: state.authReducer,
binnacleReducer: state.binnacleReducer,
});
const mapDispatchToProps = (dispatch, getState) => ({
getBinnacleStatus: (binnacle) => dispatch(getBinnacleStatus(binnacle)),
getBinnacleStatusBySuper: (binnacle) =>
dispatch(getBinnacleStatusBySuper(binnacle)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Binnacle);
binnacleReducer.js
export const binnacleReducer = (state = [], action) => {
const { type, payload } = action;
switch (type) {
case SET_OWNER_SETUP:
const { binnacleIsActive } = payload;
return {
...state,
binnacleIsActive,
};
case SET_SUPER_SETUP:
const { binnacleIsActiveBySuper } = payload;
return {
...state,
binnacleIsActiveBySuper,
};
default:
return state;
}
};
binnacleActions.js
export const SET_SUPER_SETUP = "SET_SUPER_SETUP";
export const setSuperSetup = (binnacleIsActiveBySuper) => ({
type: SET_SUPER_SETUP,
payload: {
binnacleIsActiveBySuper,
},
});
thunks.js
import axios from "axios";
import { loginSuccess, loginFailed } from "../Actions/authActions";
import {
setOwnerSetup,
setSuperSetup,
loadBinnacleNotes,
binnacleNoteReview,
addNewNote,
} from "../Actions/binnacleActions";
export const getBinnacleStatusBySuper = (binnacle) => async (
dispatch,
getState
) => {
try {
const response = await axios.get(
`http://localhost:5000/getBinnacleStatusBySuper?binnacle=${binnacle}`
);
dispatch(
setSuperSetup(response.data.binnacleIsActiveBySuper.is_active_by_super)
);
} catch (e) {
alert(e);
}
};
Upvotes: 0
Views: 880
Reputation: 11915
The issue is that you're not dispatching the action returned by addBinnacleNote
. And the onClick
prop should be a function.
You've defined the mapDispatchToProps
function to return an addBinnacleNote
prop which dispatches the action but you're not using it inside the component. You're calling the imported addBinnacleNote
function instead. There are a couple of ways to solve it. You could remove the mapDispatchToProps
function and use useDispatch
to get access to the dispatch
function and dispatch the action inside the onClick
handler.
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
<Button
variant="contained"
color="primary"
onClick={() =>
dispatch(
addBinnacleNote(binnacle, noteNumber, binnacleNote, responsible, file)
)
}
>
Agregar Nota
</Button>
Or you could use the addBinnacleNote
prop inside the onClick
handler.
Upvotes: 2