即使没有更新,useEffect也会不断重新渲染组件

时间:2020-10-28 19:56:29

标签: reactjs

请帮助我是新来的人。我正在尝试创建一个简单的消息传递应用程序。

当[messages]更新时,我希望MessageForm组件稍微重新呈现。它可以做到,但即使没有更新也不会停止。

我知道这一点,因为当我检查我的redux开发工具时,我不断看到一个动作

const MessageForm = ({ getMessages, addMessages, deleteMessages, messages, roomId,}) => {
  useEffect(() => {
    getMessages(roomId);
    scrollToBottom();
  }, [messages]);

  const [formData, setFormData] = useState({
    text: "",
  });

  const { text } = formData;

  let messagesEnd;
  const scrollToBottom = () => {
    messagesEnd.scrollIntoView({ behavior: "smooth" });
  };

  const onChange = (e) =>
    setFormData({ ...formData, [e.target.name]: e.target.value });

  const onSubmit = (e) => {
    e.preventDefault();
    addMessages(text, roomId);
    setFormData({ text: "" });
  };

  let user = JSON.parse(localStorage.getItem("user"));
  let messageList = messages.messages.map((message) => {
    return message.user === user._id ? (
      <div className="row">
        <div className="container darker col-6" key={message._id}>
          <div className="username"> {message.name}</div>
          <Avatar
            size="50"
            round={true}
            src={message.avatar}
            className="right"
          />
          <p>{message.text.toString()}</p>
          <span className="time-left">
            {moments(message.createdAt).format("LLL")}
          </span>
          <span className="time-right">
            <Icon
              onClick={() => {
                deleteMessages(message._id);
              }}
              name="trash alternate"
              className="trashCan"
            />
          </span>
        </div>
      </div>
    ) : (
      <div className="row justify-content-end">
        <div className="container darker senders col-6 " key={message._id}>
          <div className="username"> {message.name}</div>
          <Avatar
            size="50"
            round={true}
            src={message.avatar}
            className="right"
          />
          <p>{message.text.toString()}</p>
          <span className="time-left">
            {moments(message.createdAt).format("LLL")}
          </span>
          <span className="time-right">
            <Icon
              onClick={() => {
                deleteMessages(message._id);
              }}
              name="trash alternate"
              className="trashCan"
            />
          </span>
        </div>
      </div>
    );
  });

  return (
    <div className="messageArea">
      <div className="textarea">
        {messageList}
        <div
          style={{ float: "left", clear: "both" }}
          ref={(el) => {
            messagesEnd = el;
          }}
        ></div>
      </div>

      <form className="row inputBox" onSubmit={onSubmit}>
        <div className="col-10">
          <input
            type="text"
            className="form-control"
            placeholder="Enter Message"
            aria-label="Enter Message"
            aria-describedby="basic-addon2"
            id="text"
            value={text}
            name="text"
            onChange={onChange}
          />
        </div>
        <div className="col-2">
          <button className="btn btn-outline-secondary" type="submit">
            Send
          </button>
        </div>
      </form>
    </div>
  );
};
const mapDispatchToProps = (dispatch) => ({
  addMessages: (text, roomId) => dispatch(addMessages(text, roomId)),
  getMessages: (roomId) => dispatch(getMessages(roomId)),
  deleteMessages: (id) => dispatch(deleteMessages(id)),
});

const mapStateToProps = (state, props) => ({
  messages: state.messages,
  roomId: props.location.state.roomId,
});

export default connect(mapStateToProps, mapDispatchToProps)(MessageForm);

2 个答案:

答案 0 :(得分:1)

有两个问题。

  1. 您正在调用awk 'BEGIN {FS = OFS = "\t"} {for (i=4; i<=12; i+=2) {sub(/./,"&\t",$i)1;} print $0};' file1 ,这可能会更新| awk 'BEGIN {FS=OFS="\t"} FNR==NR {a[$1,$2,$5]; next} FNR==1 { next } {for (i=4; i<=12; i+=3) {print $0, (($1,$2,$4) in a ? "ref":"dev"), (($1,$2,$i + 1 ) in a ? "ref":"dev")}}' file2 - 的方法都是props,如果更改,则整个组件都会更新。 useEffect不能控制父组件,因此,每次父组件更新时,子组件也会进行控制。
  2. 第二个问题是您在getMessages中调用一个方法,该方法将重新加载messages,然后它将再次调用useEffect

我可以通过将messages移出该组件来解决此问题,或者将if语句放入useEffect中以查看是否需要调用getMessages

答案 1 :(得分:0)

除了@nzajt的答案外,也许您不需要使用“消息”作为对useEffect的依赖。只需将其视为componentDidMount

 useEffect(() => {
    getMessages(roomId);
    scrollToBottom();
  }, []);

这样,它不会无限期地重新渲染,但是在第一个渲染之后您将不再获得任何更新。 如果您要实时查找某些内容,请使用websocket查看一些内容,设置侦听器,或者使getMessages函数每隔几秒钟运行一次。