【问题标题】:TypeError: dispatch is not a function in my thunksTypeError: dispatch is not a function in my thunks
【发布时间】:2021-04-03 05:27:06
【问题描述】:

我有错误:

TypeError: dispatch is not a function

在这行代码dispatch(addNewNote(response.data.message));

我不知道为什么会发生这个错误,因为我在 thunks.js 文件中的其他函数中有其他调度工作正常。

我真的需要帮助,任何建议都将不胜感激。

请考虑以下代码:

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);
  }
};

编辑:

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);

编辑 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);
  }
};

【问题讨论】:

  • 你能把你打电话给addBinnacleNote的代码附上吗?
  • 感谢您的回复,我已经更新了帖子。

标签: reactjs redux react-redux redux-thunk


【解决方案1】:

问题是您没有调度addBinnacleNote 返回的操作。而onClick 属性应该是一个函数。

您已经定义了 mapDispatchToProps 函数以返回一个 addBinnacleNote 属性,该属性会调度该操作,但您并未在组件内使用它。您正在调用导入的 addBinnacleNote 函数。有几种方法可以解决它。您可以删除mapDispatchToProps 函数并使用useDispatch 来访问dispatch 函数并在onClick 处理程序中调度操作。

import { useDispatch } from 'react-redux'

const dispatch = useDispatch()
<Button
  variant="contained"
  color="primary"
  onClick={() =>
    dispatch(
      addBinnacleNote(binnacle, noteNumber, binnacleNote, responsible, file)
    )
  }
>
  Agregar Nota
</Button>

或者您可以在 onClick 处理程序中使用 addBinnacleNote 属性。

【讨论】:

  • 谢谢,这很有帮助,现在正在工作,我有一个最后的疑问,当我触发一个 thunk 函数并且在 thunk 内部时,我有另一个组件,我向我的减速器发送一个动作,我'没有收到此错误,这就是我感到困惑的原因。您可以推荐阅读的任何文档或对此的微小解释?
  • @DiegoDuarte 你能分享其他组件的代码吗?
  • 另外,我将 onClick 属性更改为:onClick={() => dispatch(addBinnacleNote(binnacle, noteNumber, binnacleNote, responsibility, file))}。否则函数会触发到无限循环。
  • @DiegoDuarte 我的错。 onClick 属性当然应该是一个函数。刚刚编辑了我的答案。
  • 完成,您可以在 EDIT 2 中看到我在说什么。
猜你喜欢
  • 1970-01-01
  • 2021-10-02
  • 2017-04-13
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 2020-03-26
  • 2021-11-12
  • 2015-09-18
相关资源
最近更新 更多