繁体   English   中英

如何在发布成功后立即加载数据与 Reactjs 上的 useEffect 反应

[英]How to load data imediately after posting successfully in react with useEffect on Reactjs

我正在开发一个具有事件 Model 的 Mern 堆栈应用程序,该事件有很多评论。 我想要的是在成功创建评论后加载评论,但我收到一条错误消息。

React Hook "useEffect" is called in function "onSubmit" which is neither a React function component or a custom React Hook function

当我在基于类的组件中执行此操作时有效,但我将代码更改为基于 function 的组件。 如何在成功创建后立即加载评论?

这是我的代码。

 export default function EventAndComments(props) {
    const EventComment = (props) => (
      <CardContent>
      <Typography variant="body2" color="textSecondary" component="p">
      {props.comment.name}
      </Typography>
      <Typography variant="body2" color="textSecondary" component="p">
      {props.comment.description}
      </Typography>
     </CardContent>
   );
   
   const theme = useTheme();
   const [events, setEventData] = useState([]);
   const [comments, setCommentData] = useState([]);

   const useStyles = makeStyles((theme) => ({
     root: {
       maxWidth: 850,
     },
     media: {
       height: 0,

       paddingTop: "86%", // 16:9
       display: "flex",
       flexDirection: "column",
       alignItems: "center",
     },
     expand: {
       transform: "rotate(0deg)",
       marginLeft: "auto",
       transition: theme.transitions.create("transform", {
       duration: theme.transitions.duration.shortest,
    }),
   },
    expandOpen: {
    transform: "rotate(180deg)",
   },
   avatar: {
    backgroundColor: red[500],
  },
 }));

 const classes = useStyles();
 const [expanded, setExpanded] = React.useState(false);

 const handleExpandClick = () => {
   setExpanded(!expanded);
  };

  useEffect(() => {
    axios
    .get(
      "http://localhost:9000/events/" +
      props.match.params.id +
      "/eventcomments"
    )

    .then((response) => {
      setEventData(response.data);
    })

    .catch(function (error) {
      console.log(error);
    });
 }, []);

 useEffect(() => {
   axios
   .get(
     "http://localhost:9000/events/" +
      props.match.params.id +
      "/eventcomments"
   )

   .then((response) => {
     setCommentData(response.data.eventcomments);
   })
   .catch(function (error) {
     console.log(error);
   });
 }, []);


 const nowIso = new Date();
 const getTitle = (startDateTs, endDateTs) => {
   const now = Date.parse(nowIso);

   if (endDateTs <= now) {
    return "Started:" + " " + moment(startDateTs).format("LLLL");
   }

  if (startDateTs < now && endDateTs > now) {
    return "Live:" + " " + moment(startDateTs).format("LLLL");
  }

  return "Starting:" + " " + moment(startDateTs).format("LLLL");
};

const getEnded = (startDateTs, endDateTs) => {
  const now = Date.parse(nowIso);

  if (endDateTs <= now) {
    return "Ended:" + " " + moment(startDateTs).format("LLLL");
  }

  if (startDateTs < now && endDateTs > now) {
    return "Will End:" + " " + moment(startDateTs).format("LLLL");
  }

  return "Ends:" + " " + moment(startDateTs).format("LLLL");
};

const [eventDescription, setEventComment] = React.useState("");
const [name, setName] = React.useState("");

const handleChange = (parameter) => (event) => {
  if (parameter === "name") {
    setName(event.target.value);
   }
  if (parameter === "description") {
    setEventComment(event.target.value);
  }
};

const onSubmit = useCallback(
  (e) => {
    e && e.preventDefault();
    axios
      .post(
       "http://localhost:9000/events/" +
        props.match.params.id +
        "/eventcomment",
      { name: name, description: eventDescription }
     )
     .then(function (response) {
       setCommentData(response.data.eventcomments);
     })
     .catch(function (error) {
       console.log(error);
     });
  },
  [props.match.params.id, name, eventDescription]
 );

let eventCommentList = comments.map((comment, k) => (
  <EventComment comment={comment} key={k} />
));



  return (
<Grid
  container
  spacing={0}
  direction="column"
  alignItems="center"
  justify="center"
  style={{ minHeight: "100vh" }}
>
  <Card className={classes.root}>
    <h3
      style={{
        background: "   #800000",
        color: "white",
        textAlign: "center",
      }}
      className={classes.cardheader}
    >
      {events.title}
    </h3>
    <CardHeader
      avatar={
        <Avatar aria-label="recipe" className={classes.avatar}>
          CB
        </Avatar>
      }
      action={
        <IconButton aria-label="settings">
          <MoreVertIcon />
        </IconButton>
      }
      title={getTitle(
        Date.parse(events.startingDate),
        Date.parse(events.closingDate)
      )}
      subheader={getEnded(
        Date.parse(events.startingDate),
        Date.parse(events.closingDate)
      )}
      style={{ background: "#DCDCDC" }}
    />
    <CardMedia
      className={classes.media}
      image={events.eventImage}
      title="Paella dish"
    />
    <CardContent>
      <Typography variant="body2" color="textSecondary" component="p">
        {events.description}
      </Typography>
    </CardContent>
  </Card>
  <CardContent>{eventCommentList}</CardContent>
  <form
    className={classes.root}
    noValidate
    autoComplete="off"
    onSubmit={onSubmit}
  >
    <FormControl>
      <InputLabel htmlFor="component-simple">Name</InputLabel>
      <Input
        id="component-simple"
        value={name}
        onChange={handleChange("name")}
        label="Name"
      />
    </FormControl>

    <FormControl variant="outlined">
      <InputLabel htmlFor="component-outlined">Description</InputLabel>
      <OutlinedInput
        id="component-outlined"
        value={eventDescription}
        onChange={handleChange("description")}
        label="Description"
      />
    </FormControl>
    <input
      type="submit"
      className="btn btn-outline-warning btn-block mt-4"
    />
  </form>
 </Grid>
);

}

`

您只能在顶层使用钩子,请阅读 “钩子规则”

在您的情况下,为什么不在请求成功时更新 state?

const onSubmit = (e) => {
  e.preventDefault();
  axios
    .post(
      "http://localhost:9000/events/" + props.match.params.id + "/eventcomment",
      { name: name, description: eventDescription }
    )
    .then(function (response) {
      setCommentData(response.data.eventcomments);
    })
    .catch(function (error) {
      console.log(error);
    });
};
export default function EventAndComments(props) {
  const EventComment = (props) => (
    <CardContent>
      <Typography variant="body2" color="textSecondary" component="p">
        {props.comment.name}
      </Typography>
      <Typography variant="body2" color="textSecondary" component="p">
        {props.comment.description}
      </Typography>
    </CardContent>
  );

  const theme = useTheme();
  const [events, setEventData] = useState([]);
  const [comments, setCommentData] = useState([]);

  const useStyles = makeStyles((theme) => ({
    root: {
      maxWidth: 850,
    },
    media: {
      height: 0,

      paddingTop: "86%", // 16:9
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
    },
    expand: {
      transform: "rotate(0deg)",
      marginLeft: "auto",
      transition: theme.transitions.create("transform", {
        duration: theme.transitions.duration.shortest,
      }),
    },
    expandOpen: {
      transform: "rotate(180deg)",
    },
    avatar: {
      backgroundColor: red[500],
    },
  }));

  const classes = useStyles();
  const [expanded, setExpanded] = React.useState(false);

  const handleExpandClick = () => {
    setExpanded(!expanded);
  };

  // ---- there is new -------
  const fetchCommentList = useCallback(()=>{
    return axios
    .get(
      "http://localhost:9000/events/" +
        props.match.params.id +
        "/eventcomments"
    )
    .then((response) => {
      setCommentData(response.data.eventcomments);
    })
    .catch(function (error) {
      console.log(error);
    });
  },[props.match.params.id])


  useEffect(() => {
    // first time to fetch data
    fetchCommentList()
  }, [fetchCommentList]);
 // -----------------------------

  const nowIso = new Date();
  const getTitle = (startDateTs, endDateTs) => {
    const now = Date.parse(nowIso);

    if (endDateTs <= now) {
      return "Started:" + " " + moment(startDateTs).format("LLLL");
    }

    if (startDateTs < now && endDateTs > now) {
      return "Live:" + " " + moment(startDateTs).format("LLLL");
    }

    return "Starting:" + " " + moment(startDateTs).format("LLLL");
  };

  const getEnded = (startDateTs, endDateTs) => {
    const now = Date.parse(nowIso);

    if (endDateTs <= now) {
      return "Ended:" + " " + moment(startDateTs).format("LLLL");
    }

    if (startDateTs < now && endDateTs > now) {
      return "Will End:" + " " + moment(startDateTs).format("LLLL");
    }

    return "Ends:" + " " + moment(startDateTs).format("LLLL");
  };

  const [eventDescription, setEventComment] = React.useState("");
  const [name, setName] = React.useState("");

  const handleChange = (parameter) => (event) => {
    if (parameter === "name") {
      setName(event.target.value);
    }
    if (parameter === "description") {
      setEventComment(event.target.value);
    }
  };
  //  --------   there is new -----------
  const onSubmit = useCallback(
    (e) => {
      e && e.preventDefault();
      axios
        .post(
          "http://localhost:9000/events/" +
            props.match.params.id +
            "/eventcomment",
          { name: name, description: eventDescription }
        )
        .then(function (response) {
          // what content of the `response` ?
          // setCommentData(response.data.eventcomments);
          // there is a problem 
          // is your `post` http request can get all comments? 
          // how about your `get` http request ?
          // normally `get` http request to get resource
          // `post` http request to create new resource
          // so there should be use your `get` request to fetch new data 
          fetchCommentList()
        })
        .catch(function (error) {
          console.log(error);
        });
    },
    [props.match.params.id, name, eventDescription]
  );
  // -------------------------
  const eventCommentList = comments.map((comment, k) => (
    <EventComment comment={comment} key={k} />
  ));

  return (
    <Grid
      container
      spacing={0}
      direction="column"
      alignItems="center"
      justify="center"
      style={{ minHeight: "100vh" }}
    >
      <Card className={classes.root}>
        <h3
          style={{
            background: "   #800000",
            color: "white",
            textAlign: "center",
          }}
          className={classes.cardheader}
        >
          {events.title}
        </h3>
        <CardHeader
          avatar={
            <Avatar aria-label="recipe" className={classes.avatar}>
              CB
            </Avatar>
          }
          action={
            <IconButton aria-label="settings">
              <MoreVertIcon />
            </IconButton>
          }
          title={getTitle(
            Date.parse(events.startingDate),
            Date.parse(events.closingDate)
          )}
          subheader={getEnded(
            Date.parse(events.startingDate),
            Date.parse(events.closingDate)
          )}
          style={{ background: "#DCDCDC" }}
        />
        <CardMedia
          className={classes.media}
          image={events.eventImage}
          title="Paella dish"
        />
        <CardContent>
          <Typography variant="body2" color="textSecondary" component="p">
            {events.description}
          </Typography>
        </CardContent>
      </Card>
      <CardContent>{eventCommentList}</CardContent>
      <form
        className={classes.root}
        noValidate
        autoComplete="off"
        onSubmit={onSubmit}
      >
        <FormControl>
          <InputLabel htmlFor="component-simple">Name</InputLabel>
          <Input
            id="component-simple"
            value={name}
            onChange={handleChange("name")}
            label="Name"
          />
        </FormControl>

        <FormControl variant="outlined">
          <InputLabel htmlFor="component-outlined">Description</InputLabel>
          <OutlinedInput
            id="component-outlined"
            value={eventDescription}
            onChange={handleChange("description")}
            label="Description"
          />
        </FormControl>
        <input
          type="submit"
          className="btn btn-outline-warning btn-block mt-4"
        />
      </form>
    </Grid>
  );
}


================================更新==================

试试这个方法; )

const [comments, setCommentData] = useState([]);

const onSubmit = useCallback(
  (e) => {
      e && e.preventDefault();
      axios
        .post(
          "http://localhost:9000/events/" +
            props.match.params.id +
            "/eventcomment",
          { name: name, description: eventDescription }
        )
        .then(function (response) {
          console.log(response);
          setCommentData(response.data.eventcomments);
        })
        .catch(function (error) {
          console.log(error);
        });
      },
    [props.match.params.id, name, eventDescription],
  )

  useEffect(()=>{
    onSubmit()
  },[onSubmit])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM