useEffect内部的状态始终使用React Hooks引用初始状态 [英] state inside useEffect refers the initial state always with React Hooks

查看:155
本文介绍了useEffect内部的状态始终使用React Hooks引用初始状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每次我从另一个组件发出消息时,我都无法获得消息的完整列表.这是钩子和视图组件:

Every time I emit a message from another component, I can't get the full list of messages. Here is the hook and view component:

export function useChat() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = openSocket("http://localhost:3003");
    socket.on("chat message", msg => {
      const newState = update(messages, { $push: [msg] });
      setMessages(newState);
    });
  }, []);

  return { messages };
}

不幸的是,状态不会持久,并且总是显示最后一条消息:

Unfortunately the state doesn't persist and shows always the last message:

export const HookSockets = () => {
  const { messages } = useChat();
  return (
    <div>
      {messages.map((message, index) => (
        <div key={index}>{message}</div>
      ))}
    </div>
  );
};

如果我按常规方式进行操作,那么一切都会按预期进行:

If I do this the regular way, everything works as intended:

export class ClassSockets extends Component {
  state = {
    socket: openSocket("http://localhost:3003"),
    messages: [],
    message: ""
  };

  componentDidMount() {
    this.state.socket.on("chat message", msg => {
      const newState = update(this.state, {
        messages: { $push: [msg] }
      });
      this.setState(newState);
    });
  }

  handleClick = () => {
    this.state.socket.emit("chat message", this.state.message);
    this.setState({ message: "" });
  };

  handleChange = event => {
    this.setState({ message: event.target.value });
  };

  render() {
    return (
      <div>
        <div>Sockets</div>
        <div>{this.state.messages}</div>
        <input
          type="text"
          value={this.state.message}
          onChange={this.handleChange}
        />
        <button onClick={this.handleClick}>Send Message</button>
      </div>
    );
  }
}

推荐答案

由于您编写了useEffect以便在组件的初始安装时执行,因此它会创建一个引用messages初始值的闭包,即使消息已更新也是如此. ,那么在后续调用中它仍将引用相同的值

Since you have written your useEffect to execute on initial mount of component, it creates a closure which references the initial value of messages and even if the messages update, it will still refer to the same value on subsequent calls

您应该将useEffect配置为在初始安装和消息更改时运行

You should instead configure the useEffect to run on initial mount and messages change

export function useChat() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = openSocket("http://localhost:3003");
    socket.on("chat message", msg => {
      const newState = update(messages, { $push: [msg] });
      setMessages(newState);
    });
  }, [messages]);

  return { messages };
} 

否则您可以使用回调模式来更新状态

or else you could use the callback pattern to update state

export function useChat() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = openSocket("http://localhost:3003");
    socket.on("chat message", msg => {
      setMessages(prevMessages => update(prevMessages, { $push: [msg] }););
    });
  }, []);

  return { messages };
}

这篇关于useEffect内部的状态始终使用React Hooks引用初始状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆