更新项目数组时无法使用 React useState 更新 UI
Trouble updating UI with React useState when updating an array of items
很难用 React 和 useState 更新我的 UI。任何帮助将不胜感激。基本上我想做的只是删除用户添加的项目。
interface RedirectUrls {
url: string;
}
const [redirectUrls, setRedirectUrls] = useState<RedirectUrls[]>([
{
url: ''
}
])
function deleteRedirectUrl(url): void {
let tmpUrls = redirectUrls
tmpUrls = tmpUrls.filter(item => item.url !== url)
setRedirectUrls(tmpUrls)
}
function handleChange (index, event): void {
const tmpUrls = [...redirectUrls]
tmpUrls[index].url = event.target.value
}
{redirectUrls.map((item, index) => {
return (
<div key={index}>
<input type='text' onChange={(event):void => {handleChange(index,event)}}/>
<div onClick={():void => {deleteRedirectUrl(item.url)}}>remove</div>
</div>
)
})}
几点:
- 一个组件应该return一个元素。在你的例子中,map returns 是一个元素数组,我不得不使用一个空元素(或 <React.Fragment>)
来包装集合
- 不要忘记将
value
属性 设置为 input
元素以使更改反映在元素中。
- 作为最佳实践,在处理状态变量时使用
const
而不是 let
,将它们视为不可变的,以避免丢失您的更改,尤其是当有许多状态变量导致多次渲染时
- 我们应该说明类型,因为文件是打字稿,您没有指定函数参数的类型
- 修改完成后应调用 setter
import React, { useState } from 'react';
interface RedirectUrls {
url: string;
}
const App = () => {
const [redirectUrls, setRedirectUrls] = useState<RedirectUrls[]>([
{
url: 'firstUrl'
},
{
url: 'secondUrl'
}
])
function deleteRedirectUrl(url: string): void {
const tmpUrls = redirectUrls.filter(item => item.url !== url)
setRedirectUrls(tmpUrls)
}
function handleChange(index: number, event: React.ChangeEvent<HTMLInputElement>): void {
const tmpUrls = [...redirectUrls]
tmpUrls[index].url = event.target.value
setRedirectUrls(tmpUrls);
}
return <>{redirectUrls.map((item, index) => <div key={index}>
<input type='text' value={item.url} onChange={(event): void => { handleChange(index, event) }} />
<div onClick={(): void => { deleteRedirectUrl(item.url) }}>remove</div>
</div>)}</>;
}
export default App;
很难用 React 和 useState 更新我的 UI。任何帮助将不胜感激。基本上我想做的只是删除用户添加的项目。
interface RedirectUrls {
url: string;
}
const [redirectUrls, setRedirectUrls] = useState<RedirectUrls[]>([
{
url: ''
}
])
function deleteRedirectUrl(url): void {
let tmpUrls = redirectUrls
tmpUrls = tmpUrls.filter(item => item.url !== url)
setRedirectUrls(tmpUrls)
}
function handleChange (index, event): void {
const tmpUrls = [...redirectUrls]
tmpUrls[index].url = event.target.value
}
{redirectUrls.map((item, index) => {
return (
<div key={index}>
<input type='text' onChange={(event):void => {handleChange(index,event)}}/>
<div onClick={():void => {deleteRedirectUrl(item.url)}}>remove</div>
</div>
)
})}
几点:
- 一个组件应该return一个元素。在你的例子中,map returns 是一个元素数组,我不得不使用一个空元素(或 <React.Fragment>) 来包装集合
- 不要忘记将
value
属性 设置为input
元素以使更改反映在元素中。 - 作为最佳实践,在处理状态变量时使用
const
而不是let
,将它们视为不可变的,以避免丢失您的更改,尤其是当有许多状态变量导致多次渲染时 - 我们应该说明类型,因为文件是打字稿,您没有指定函数参数的类型
- 修改完成后应调用 setter
import React, { useState } from 'react';
interface RedirectUrls {
url: string;
}
const App = () => {
const [redirectUrls, setRedirectUrls] = useState<RedirectUrls[]>([
{
url: 'firstUrl'
},
{
url: 'secondUrl'
}
])
function deleteRedirectUrl(url: string): void {
const tmpUrls = redirectUrls.filter(item => item.url !== url)
setRedirectUrls(tmpUrls)
}
function handleChange(index: number, event: React.ChangeEvent<HTMLInputElement>): void {
const tmpUrls = [...redirectUrls]
tmpUrls[index].url = event.target.value
setRedirectUrls(tmpUrls);
}
return <>{redirectUrls.map((item, index) => <div key={index}>
<input type='text' value={item.url} onChange={(event): void => { handleChange(index, event) }} />
<div onClick={(): void => { deleteRedirectUrl(item.url) }}>remove</div>
</div>)}</>;
}
export default App;