handleClick函数中的useDispatch

时间:2020-10-12 20:54:08

标签: reactjs redux react-hooks redux-react-hook

如何在单击按钮时调度操作?我想调度一个进行异步调用的动作。如果这不可能,那么实际的方法是什么?

import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";

import allActions from "../redux/actions/index";

import axios from "axios";

const useStyles = makeStyles((theme) => ({
  root: {
    flexGrow: 1,
    marginBottom: 10,
  },
}));

export default function ChatPreview({ chat }) {
  const [secondary, setSecondary] = React.useState(false);
  const lastMessageId = chat.messages.slice(-1)[0];
  const [message, setMessage] = useState(null);
  const [error, setError] = useState(null);
  const classes = useStyles();
  const user = useSelector((state) => state.user);
  const token = localStorage.getItem("IdToken").split(" ")[1];
  const dispatch = useDispatch;
  //Get otherUser
  let otherUser = {};
  chat.users.map((user_) => {
    if (user_.username !== user.username) otherUser = user_;
  });

  useEffect(() => {
    let headers = { Authorization: `Bearer ${token}` };

    axios
      .get(`/messages/message/${lastMessageId}`, { headers })
      .then((res) => {
        setMessage(res.data);
      })
      .catch((err) => {
        setError(err);
      });
  }, []);

  let primary = false;
  if (user && message) {
    if (user._id === message.author) primary = true;
  }

  const handleClick = () => {
    dispatch(allActions.inboxActions.deleteChat(chat._id, token));
  };

  const chatPreviewMarkup =
    message && user ? (
      <List>
        <ListItem>
          <ListItemAvatar>
            <Avatar alt={otherUser.username} src={otherUser.avatar} />
          </ListItemAvatar>
          <ListItemText
            primary={
              primary ? (message.read ? "read" : "unread") : message.content
            }
            secondary={secondary ? "Secondary text" : null}
          />
          <ListItemSecondaryAction>
            <IconButton edge="end" aria-label="delete">
              <DeleteIcon onClick={handleClick} />
            </IconButton>
          </ListItemSecondaryAction>
        </ListItem>
      </List>
    ) : (
      <p>...loading</p>
    );

  return chatPreviewMarkup;
}

返回以下错误:

错误:无效的挂钩调用。挂钩只能在功能组件的主体内部调用。发生这种情况可能是由于以下原因之一:

  1. 您可能使用了不匹配的React和渲染器版本(例如React DOM)
  2. 您可能正在违反挂钩规则
  3. 您可能在同一应用中拥有多个React副本

2 个答案:

答案 0 :(得分:2)

function MyComponent() {
  const dispatch = useDispatch()

  const handleClick = () => {
    dispatch(actionCreator())
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  )
}

答案 1 :(得分:1)

您需要在回调之外调用useDispatch(),因为挂钩必须位于组件的顶层。

您已经几乎做到了,但是您被错字打乱了。您需要更改

const dispatch = useDispatch;

const dispatch = useDispatch();

缺少括号意味着您在useDispatch内部才真正调用handleClick。变量dispatch是挂钩本身,而不是返回值,因此,当您调用dispatch(allActions...)时,实际上是在调用useDispatch(allActions...)并收到错误。