自定义React组件(react-hook)不重新渲染

时间:2019-12-23 01:04:37

标签: javascript reactjs react-hooks

我有一个组件,该组件从mongoDB中获取数据,然后呈现子组件列表。它有一个“列表”组件,我有一个帖子,它将新成员添加到数据库中。另外,我尝试获取列表以重新获取数据并重新呈现列表组件。

列表组件:

import React, { useState, useEffect } from "react";
import axios from "axios";
import Spinner from "react-bootstrap/Spinner";
import { toast } from "react-toastify";
import DatePicker from "react-datepicker";
import useForm from "react-hook-form";

import { css } from "glamor";
import "react-toastify/dist/ReactToastify.css";
import "react-datepicker/dist/react-datepicker.css";
import "../Styles/ReactDatePicker.css";

import Member from "./Member";

const { getFamily, getMembers, postMember } = require("../Utils/Service");

const MemberList = () => {
  const [family, setFamily] = useState({});
  const [familyMembers, setFamilyMembers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [date, setDate] = useState(new Date());

  const { handleSubmit, register, errors } = useForm();

  async function fetchData() {
    getFamily.then(result => {
      setFamily(result);
    });

    getMembers.then(result => {
      try {
        setFamilyMembers(
          result.map((child, index) => (
            <Member
              key={index}
              index={child._id}
              balance={child.balance}
              firstName={child.firstName}
              lastName={child.lastName}
              birthday={child.birthday}
              role={child.role[0]}
            />
          ))
        );
      } catch (e) {
        toast.error("500: Error with Service Call", {
          position: "top-right",
          autoClose: 5000,
          hideProgressBar: false,
          closeOnClick: true,
          pauseOnHover: true,
          draggable: true,
          className: css({
            background: "#ed5565 !important"
          })
        });
      } finally {
        setLoading(false);
      }
    });
  }

  useEffect(() => {
    if (loading) {
      fetchData();
    }
  }, [loading]);

  // const handleDateChange = date => {
  //   setDate(date)
  // }
  const onSubmit = data => {
    data.familyId = "5dddf14df965552b3da57be1";
    postMember(data).then(
      ????????????
    );
  };

  return (
    <div className="ibox">
      <div className="ibox-title">
        <h5>{family.name}</h5>
        <div className="ibox-tools">
          <span className="label label-warning-light float-right">
            {familyMembers.length} Member(s)
          </span>
        </div>
      </div>
      <div className="ibox-content">
        <div className="feed-activity-list">
          {loading ? (
            <Spinner animation="grow" role="status" variant="dark">
              <span className="sr-only">Loading...</span>
            </Spinner>
          ) : (
            familyMembers
          )}
        </div>
        <div className="d-flex">
          <a
            className="btn btn-primary text-white m-t"
            data-toggle="modal"
            data-target={"#newMemberModel"}
          >
            <i className="fa fa-plus"></i> New Member
          </a>
          <a
            className="btn btn-danger text-white m-t m-l"
            data-toggle="modal"
            data-target={"#removeMemberModel"}
          >
            <i className="fa fa-minus"></i> Remove Member
          </a>
        </div>
      </div>

      {/* New Member Model */}
      <div
        className="modal inmodal"
        id={"newMemberModel"}
        tabIndex="-1"
        role="dialog"
        style={{ display: "none" }}
        aria-hidden="true"
      >
        <div className="modal-dialog">
          <div className="modal-content animated fadeIn">
            <div className="modal-header">
              <button type="button" className="close" data-dismiss="modal">
                <span aria-hidden="true">×</span>
                <span className="sr-only">Close</span>
              </button>
              <h4 className="modal-title">New Family Member</h4>
            </div>
            <form onSubmit={handleSubmit(onSubmit)}>
              <div className="modal-body">
                <div className="row">
                  <div className="col">
                    <div className="form-group">
                      <label>First Name</label>
                      <input
                        type="text"
                        placeholder="First Name"
                        className="form-control"
                        name="firstName"
                        ref={register({
                          required: true,
                          pattern: {
                            value: /^[a-zA-Z]+$/i,
                            message: "Invalid First Name"
                          }
                        })}
                      />
                      <div className="text-danger">
                        {errors.firstName && errors.firstName.message}
                      </div>
                    </div>
                    <div className="form-group">
                      <label className="font-normal">Birthday</label>
                      <div className="input-group date">
                        {/* <DatePicker
                          selected={date}
                          onChange={handleDateChange}
                          placeholderText="Click to select a date"
                          isClearable
                          peekNextMonth
                          showMonthDropdown
                          showYearDropdown
                          dropdownMode="select"
                          ref={e =>register({
                            name: "Birthday",
                            required: false
                          })}
                        /> */}
                        <input
                          type="text"
                          placeholder="01/01/01"
                          className="form-control"
                          name="birthDate"
                          ref={register({
                            required: false
                          })}
                        />
                      </div>
                    </div>
                  </div>
                  <div className="col">
                    <div className="form-group">
                      <label>Last Name</label>
                      <input
                        type="text"
                        placeholder="Last Name"
                        className="form-control"
                        name="lastName"
                        ref={register({
                          required: true,
                          pattern: {
                            value: /^[a-zA-Z]+$/i,
                            message: "Invalid Last Name"
                          }
                        })}
                      />
                      <div className="text-danger">
                        {errors.lastName && errors.lastName.message}
                      </div>
                    </div>
                    <div className="form-group">
                      <label>Role</label>
                      <select
                        className="custom-select"
                        name="role"
                        ref={register({ required: true })}
                      >
                        <option defaultValue>Select Role</option>
                        <option value="Adult">Adult</option>
                        <option value="Child">Child</option>
                      </select>
                    </div>
                  </div>
                </div>
              </div>
              <div className="modal-footer">
                <button
                  type="button"
                  className="btn btn-white"
                  data-dismiss="modal"
                >
                  Close
                </button>
                <button type="submit" className="btn btn-primary">
                  Add Member
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>

      {/* Remove Member Model */}
      <div
        className="modal inmodal"
        id={"removeMemberModel"}
        tabIndex="-1"
        role="dialog"
        style={{ display: "none" }}
        aria-hidden="true"
      >
        <div className="modal-dialog">
          <div className="modal-content animated fadeIn">
            <div className="modal-header">
              <button type="button" className="close" data-dismiss="modal">
                <span aria-hidden="true">×</span>
                <span className="sr-only">Close</span>
              </button>
              <h4 className="modal-title">Remove Family Member</h4>
            </div>
            <div className="modal-body"></div>
            <div className="modal-footer">
              <button
                type="button"
                className="btn btn-white"
                data-dismiss="modal"
              >
                Close
              </button>
              <button type="button" className="btn btn-danger">
                Remove Member
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default MemberList;
onSubmit函数中的代码中,

.then内部发布数据,这是我试图重新呈现整个组件和/或重新获取数据的地方。

2 个答案:

答案 0 :(得分:1)

现在,您的useEffect仅取决于属性loading,如果您更改属性,则效果将再次运行。

https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

答案 1 :(得分:0)

在您的组件中,您可以调用this.forceUpdate()强制重新渲染。

我认为,如果您将.then()内部的回调设为异步函数,那么您也可以在.then()块内再次调用fetchData函数。

postMember(data).then(  异步()=> this.fetchData()     );

postMember(data).then( ()=> this.forceUpdate()     );