The code below is a small, very simplified snippet from a React messaging app
const { useState } = React;
const Chat = () => {
const [myMessages, setMyMessages] = useState([]);
const [message, setMessage] = useState("");
const [myButtons, setMyButtons] = useState([{}]);
const addNewMessage = () => {
let buttonIndex = myMessages.length;
setMyButtons(myButtons => [...myButtons, { value: "Copy message" }]);
let newMessage =
(<div>
<div>{message}</div>
<button className="copy-to-clipboard-button" onClick={() => { copyToClipboard(buttonIndex, message); }}>
{myButtons[buttonIndex].value}
</button>
</div>);
setMyMessages([...myMessages, newMessage]);
};
const copyToClipboard = (i, text) => {
alert("copied");
navigator.clipboard.writeText(text);
let allButtons = myButtons.slice();
allButtons[i].value = "Copied!";
setMyButtons([...allButtons]);
};
const handleChange = (event) => {
setMessage(event.target.value);
};
return (
<div>
<div style={{ maxHeight: "80vh", minHeight: "90vh", maxWidth: "96vw" }}>
<div>{myMessages.map(message => <div>{message}</div>)}
<input
type="text"
id="message"
name="message"
onChange={handleChange}
value={message}
/>
<button onClick={addNewMessage}>Go!</button>
</div>
</div>
</div>
)
};
ReactDOM.createRoot(document.body).render(<Chat />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
This code is for demonstration purposes only in order to spotlight the problem I’m trying to solve. Basically, when a new message is added, a copy to clipboard button is added with it. The value of each these dynamically added buttons is set to {myButtons[buttonIndex].value}
with the intention that I’m tying the button’s value to a state variable that can be updated and rendered. This value is set correctly when the component is first added.
When a ‘copy-to-clipboard-button’ is clicked, the copyToClipboard
method is called and the copy functionality works correctly. The next step is to change the button value to "Copied!". Although the array is updated correctly, the value of the button is not updated. I suspect that the problem is that when the button is created, it sets the value as a static value and is not tied to that state variable going forward. My thinking is that there is a way to indicate that the button value should be tied to state ongoing, but I’m not able to find the right syntax. Perhaps there’s a better way to approach this altogether. Looking for some guidance. Thanks!
2
Answers
if i got your mean correct , create a separate component for each message and its associated button. This way, each button’s value would be tied to its own state variable and can be updated independently
You need a function to trigger references:
If you use
after compile:
this leads to static compilation at creation time instead use function