【问题标题】:useDispatch in handleClick functionhandleClick 函数中的 useDispatch
【发布时间】:2020-10-12 20:54:08
【问题描述】:

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

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

返回以下错误:

错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用。这可能是由于以下原因之一:

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

【问题讨论】:

  • onClick 应该收到一个函数引用,您调用的是一个函数引用而不是传递它。将onClick={handleClick()} 更改为onClick={handleClick}。如果您仍然有问题,您可以更新,但这似乎是问题所在。
  • 也调用useDispatch()函数。
  • 我尝试这种方式时出错。
  • 您能否提供一个Minimal, Complete, and Reproducible 代码示例,以便我们了解如何以及在何处调用该钩子?

标签: reactjs redux react-redux react-hooks


【解决方案1】:

这样

function MyComponent() {
  const dispatch = useDispatch()

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

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

【讨论】:

    【解决方案2】:

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

    你已经几乎做到了,但是你被一个错字吓跑了。你需要改变

    const dispatch = useDispatch;
    

    到

    const dispatch = useDispatch();
    

    缺少的括号意味着您实际上并没有调用useDispatch,直到在您的handleClick 中。变量dispatch 是钩子本身,而不是返回值,所以当您调用dispatch(allActions...) 时,您实际上是在调用useDispatch(allActions...) 并收到错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-26
      • 2019-07-20
      • 2021-03-05
      • 1970-01-01
      • 2021-06-17
      • 1970-01-01
      • 2022-10-07
      • 2016-04-15
      相关资源
      最近更新 更多