簡體   English   中英

如何保證在使用 useState 添加之前調用重置

[英]How do I guarantee that reset is called before add using useState

我創建了一個自定義鈎子

const useMessageStorage = () => {
  const [messages, setMessages] = useState([]);
  
  const addMessages = (newMessage) => {
    setMessages(oldMessages => [...oldMessages, newMessage)]);
  }

  const clear = () => {
    setMessages([]);
  }

  return { clear, addMessages }
}

在消費者組件內部,我想做類似的事情

const { clear, addMessages } = useMessageStorage();
...

clear() // clear before adding new messages
addMessage('new message') 

以上不起作用,因為兩個調用都是異步的。 但是我想在某些特定場景中添加新消息之前清除所有消息。 如何解決這個問題? 我考慮過使用useRef但由於競爭條件我害怕使用它。

React state updates are asynchronously processed, this is true, but they are also processed in the order they are enqueued in. Since your addMessages callback uses a functional state update it will update from the previous state, not the state of the render cycle it was入隊。

// clear()
setMessages([]); // "draft" state: []

// addMessage(newMessage)
setMessages((oldMessages) => [ // updated from "draft" state: [newMessage]
  ...oldMessages,
  newMessage,
]);

您的代碼確實有效。

 const useMessageStorage = () => { const [messages, setMessages] = React.useState([]); const addMessages = (newMessage) => { setMessages((oldMessages) => [...oldMessages, newMessage]); }; const clear = () => { setMessages([]); }; return { clear, messages, addMessages }; }; function App() { const [message, setMessage] = React.useState(""); const { clear, messages, addMessages } = useMessageStorage(); const addMessage = () => { if (message) { addMessages(message); setMessage(""); } }; const clearAndAddMessage = () => { if (message) { clear(); addMessages(message); setMessage(""); } }; return ( <div className="App"> <label> Message: <input type="text" id="message" onChange={(e) => setMessage(e.target.value)} value={message} /> </label> <button type="button" onClick={addMessage}> Add Message </button> <button type="button" onClick={clearAndAddMessage}> Clear & Add Message </button> <ul> {messages.map((message, i) => ( <li key={i}>{message}</li> ))} </ul> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render( <App />, rootElement );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script> <div id="root" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM