4 回答

TA貢獻1848條經驗 獲得超10個贊
您不需要更新狀態,當單擊任何按鈕時,只需在按鈕上顯示不同的文本。
在包含所有數據的列表的父元素上添加單擊事件偵聽器,并檢查觸發click
事件的元素是否為復制按鈕。如果是,請更改其文本并設置一個計時器,將文本恢復為“復制”
演示:
const url = 'https://jsonplaceholder.typicode.com/todos';
function App() {
const [todos, setTodos] = React.useState([]);
React.useEffect(() => {
fetch(url)
.then(res => res.json())
.then(todos => setTodos(todos))
.catch(err => console.log(err.message));
}, []);
return (
<div className="App">
<TodoList todos={todos}/>
</div>
);
}
function TodoList(props) {
function changeBtnText(event) {
const target = event.target;
if (target.matches("button")) {
target.textContent = "Copied";
setTimeout(() => (target.textContent = "Copy"), 1000);
}
}
return (
<div className="todoList" onClick={changeBtnText}>
{props.todos.map(t => (
<Todo key={t.id} {...t} />
))}
</div>
);
}
function Todo({ title, completed }) {
return (
<div className="todo">
<span>TItle: {title}</span>
<button>Copy</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
font-family: sans-serif;
text-align: center;
}
.todo {
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
margin: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 10px;
}
.todo button {
padding: 5px 10px;
margin: 10px 0 0 0;
cursor: pointer;
}
<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"></div>
您還可以在 Codesandbox 上查看此演示

TA貢獻1805條經驗 獲得超9個贊
import React, { useEffect, useState, useCallback, useRef } from 'react'
import { range } from 'lodash-es'
const App = () => {
const [items, setItems] = useState(
range(100).map((val) => ({ id: val, val, text: 'Copy' })),
)
const [copiedItem, setCopiedItem] = useState<number | undefined>(undefined)
const timeout = useRef<number | undefined>(undefined)
useEffect(() => {
if (copiedItem) {
setItems((itemsState) =>
itemsState.map((item) =>
item.id === copiedItem
? { ...item, text: 'Copied' }
: { ...item, text: 'Copy' },
),
)
} else {
setItems((itemsState) =>
itemsState.map((item) => ({ ...item, text: 'Copy' })),
)
}
}, [copiedItem])
const handleClick = useCallback(
(itemId) => () => {
if (timeout.current) {
window.clearTimeout(timeout.current)
}
setCopiedItem(itemId)
timeout.current = window.setTimeout(() => {
setCopiedItem(undefined)
}, 1000)
},
[],
)
return (
<div>
{items.map((item) => (
<div key={item.id} className="mb-4">
<span className="mr-2">{item.val}</span>
<button className="p-2 bg-gray-100" onClick={handleClick(item.id)}>
{item.text}
</button>
</div>
))}
</div>
)
}
export default App
您可以使用另一種狀態copiedItem來存儲要復制的項目的 id 或索引。在 中useEffect我們可以尋找更改copiedItem以設置要復制的文本。
除此之外,我們還需要對上一個超時的引用,以便我們可以在觸發下一個項目超時之前清除它。

TA貢獻1803條經驗 獲得超6個贊
所以我嘗試使用@Agney 建議在 setState 中使用回調。這是codesanbox鏈接https://codesandbox.io/s/quirky-dubinsky-lm03x?file=/src/App.js
所以基本上我們在 setstate 回調中檢查索引以最初將其設置為復制,在超時回調中我們再次檢查相同的索引以設置回復制。
添加回答
舉報