如何解决搜索框反应中的异步行为
how to solve asynchronous behaviour in search Box react
所以我正在尝试使用 useState 和 useEffect 实现一个搜索框。我们有一个对象数组,想根据我们的搜索词过滤它。这是我的实现:
import React, {useEffect, useState} from "react";
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = []
const Setup = () => {
const [state, setState] = useState('');
useEffect(() => {
available = array.filter(a => a.value.startsWith(state));
},[state])
const show = state ? available : array;
return <>
<input value={state} onChange={e => setState(e.target.value)} type="text" className="form"/>
{show.map(a => {
return <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type}/>
})}
</>
}
const Data = (props) => {
return <>
<div>
<p>{props.value}</p>
</div>
</>
}
export default Setup;
当我们为搜索框提供有效的搜索词时(如 'T'),问题就开始了。我希望它相应地改变输出(只显示 'Tatooine')但输出没有改变。
同时,如果您在搜索词中添加另一个字符(如 'a',这会将我们的搜索词设置为 'Ta'),它将输出预期的结果。换句话说,搜索词不是同步应用的。你知道为什么吗
您只需将 toLowerCase 方法添加到您的过滤器函数中。就像这样:
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
let available = [];
const Setup = () => {
const [state, setState] = useState("");
useEffect(() => {
available = array.filter((a) => a.value.toLowerCase().startsWith(state));
}, [state]);
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{show.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
这是工作示例:here
您可以简单地拉出 useEffect。
import React, { useState } from 'react';
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = [];
const Setup = () => {
const [state, setState] = useState('');
available = array.filter(a => a.value.startsWith(state));
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={e => setState(e.target.value)}
type='text'
className='form'
/>
{show.map(a => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = props => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
useEffect
挂钩在组件挂载、重新呈现或卸载时触发。在您的情况下,由于 state
的更改,搜索字段的更改会导致重新呈现。这会导致您的 useEffect
在 状态更改后触发 并且为时已晚,无法满足您的需求。
如果您在字段中输入“Ta”,您会发现它有效,但搜索似乎落后了一步。
您可以在渲染时简单地删除 useEffect
和过滤的使用。这意味着您还可以删除围绕 available
和 show
变量的整个逻辑:
const Setup = () => {
const [state, setState] = useState("");
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{array
.filter((a) => a.value.startsWith(state))
.map((a) => (
<Data
id={a.key}
key={parseInt(a.key, 10)}
value={a.value}
type={a.type}
/>
))}
</>
);
};
Using the Effect Hook 文档中有一些很好的信息。
这个一定要解决
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
const Setup = () => {
const [state, setState] = useState("");
const [available, setAvailable] = useState(array);
useEffect(() => {
setAvailable(array.filter((a) => a.value.startsWith(state)));
}, [state]);
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{available.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
所以我正在尝试使用 useState 和 useEffect 实现一个搜索框。我们有一个对象数组,想根据我们的搜索词过滤它。这是我的实现:
import React, {useEffect, useState} from "react";
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = []
const Setup = () => {
const [state, setState] = useState('');
useEffect(() => {
available = array.filter(a => a.value.startsWith(state));
},[state])
const show = state ? available : array;
return <>
<input value={state} onChange={e => setState(e.target.value)} type="text" className="form"/>
{show.map(a => {
return <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type}/>
})}
</>
}
const Data = (props) => {
return <>
<div>
<p>{props.value}</p>
</div>
</>
}
export default Setup;
当我们为搜索框提供有效的搜索词时(如 'T'),问题就开始了。我希望它相应地改变输出(只显示 'Tatooine')但输出没有改变。 同时,如果您在搜索词中添加另一个字符(如 'a',这会将我们的搜索词设置为 'Ta'),它将输出预期的结果。换句话说,搜索词不是同步应用的。你知道为什么吗
您只需将 toLowerCase 方法添加到您的过滤器函数中。就像这样:
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
let available = [];
const Setup = () => {
const [state, setState] = useState("");
useEffect(() => {
available = array.filter((a) => a.value.toLowerCase().startsWith(state));
}, [state]);
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{show.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
这是工作示例:here
您可以简单地拉出 useEffect。
import React, { useState } from 'react';
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = [];
const Setup = () => {
const [state, setState] = useState('');
available = array.filter(a => a.value.startsWith(state));
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={e => setState(e.target.value)}
type='text'
className='form'
/>
{show.map(a => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = props => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
useEffect
挂钩在组件挂载、重新呈现或卸载时触发。在您的情况下,由于 state
的更改,搜索字段的更改会导致重新呈现。这会导致您的 useEffect
在 状态更改后触发 并且为时已晚,无法满足您的需求。
如果您在字段中输入“Ta”,您会发现它有效,但搜索似乎落后了一步。
您可以在渲染时简单地删除 useEffect
和过滤的使用。这意味着您还可以删除围绕 available
和 show
变量的整个逻辑:
const Setup = () => {
const [state, setState] = useState("");
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{array
.filter((a) => a.value.startsWith(state))
.map((a) => (
<Data
id={a.key}
key={parseInt(a.key, 10)}
value={a.value}
type={a.type}
/>
))}
</>
);
};
Using the Effect Hook 文档中有一些很好的信息。
这个一定要解决
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
const Setup = () => {
const [state, setState] = useState("");
const [available, setAvailable] = useState(array);
useEffect(() => {
setAvailable(array.filter((a) => a.value.startsWith(state)));
}, [state]);
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{available.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;