React中如何实现点击搜索按钮触发数组过滤而非实时自动过滤
实现点击搜索按钮才过滤的修改方案
核心修改逻辑
你原来的逻辑是直接用输入框实时绑定的search状态做过滤,所以每次输入都会触发重渲染过滤。我们只需要新增一个状态专门存储点击搜索后才提交的过滤参数,过滤逻辑只依赖这个提交后的参数即可。
完整修改后代码
import CountUp from 'react-countup'; import { Link } from 'react-router-dom'; import React from 'react'; import '../App.css'; /*Components ->*/ import Client from '../components/client.js' function App() { // 存储表单实时输入的临时内容,不会触发过滤 const [search, setSearch] = React.useState({ searchname: '', price: 'Free', safe: 'Safe', mcver: '1.8.9', type: 'Injected', compatibility: 'With Most Other Clients' }); // 存储点击搜索后提交的过滤参数,只有这个值变化才会触发过滤 const [filterParams, setFilterParams] = React.useState(null); // 客户端原始数据 const [client, setClient] = React.useState([ { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Impact', price: 'Free', mcversion: '1.11.2 - 1.16.5', type: 'Injected', compat: 'None (Stand alone client)', desc: 'The Impact client is an advanced utility mod for Minecraft, it is packaged with Baritone and includes a large number of useful mods.', screen: 'https://impactclient.net/', download: 'https://impactclient.net/'}, { safestatus: 'safe-status-green', safe: 'Safe (Verified)', name: 'Future', price: '15€', mcversion: '1.8.9 - 1.14.4', type: 'Injected', compat: 'None (Stand alone client)', desc: 'Vanilla, OptiFine, Forge and Liteloader support, Easy to use account manager, Auto-reconnect mod.', screen: 'https://www.futureclient.net/', download: 'https://www.futureclient.net/'} ]); // 表单输入实时更新临时状态,不触发过滤 const updateSearch = (event) => { event.persist(); setSearch((prev) => ({ ...prev, [event.target.name]: event.target.value })); }; // 点击搜索按钮才提交过滤参数 const handleSearch = () => { setFilterParams({...search}); }; return ( <body> <div className='header'><Link to='/'>Hacked Hub</Link><div className='header-links'><Link to='/about-us'>About Us</Link> | <Link to='/faq'>FAQ</Link></div></div> <div className='counter'><CountUp end={16} duration={0.5}></CountUp>+</div> <div className='counter-desc'><div className='code'>hacked clients</div> and counting...</div> <div className='nxt-tab'> <input name='searchname' value={search.searchname} onChange={updateSearch} placeholder='Search'></input> <select name='price' value={search.price} onChange={updateSearch}> <option value='Free'>Free</option> <option value='Paid'>Paid</option> </select> <select name='safe' value={search.safe} onChange={updateSearch}> <option value='Safe'>Safe</option> <option value='Probably Safe'>Probably Safe</option> <option value='Not Safe'>Not Safe (BE CAREFUL!)</option> </select> <select name='mcver' value={search.mcver} onChange={updateSearch}> <option value='1.8.9'>1.8.9</option> <option value='1.12.2'>1.12.2</option> <option value='1.16.5'>1.16.5</option> <option value='1.17+'>1.17+</option> </select> <select name='type' value={search.type} onChange={updateSearch}> <option value='Injected'>Injected</option> <option value='Mod'>Mod</option> </select> <select name='compatibility' value={search.compatibility} onChange={updateSearch}> <option value='With Most Other Clients'>With Most Other Clients</option> <option value='Stand Alone'>Stand Alone</option> </select> {/* 新增搜索按钮 */} <button onClick={handleSearch}>搜索</button> <div className='client-warning'><div className='safe-status-red'><div className='code'>⚠ WARNING ⚠</div></div> Only download clients you know are <div className='code'>100%</div> safe! If we do find a client that is a <div className='code'>rat / virus / BTC miner</div> we will tag it as <div className='safe-status-red'><div className='code'>UNSAFE IMMEDIATELY</div></div>. The saftey warnings for clients are <div className='code'>MERE RECCOMENDATIONS</div>, please do thorough research before downloading any hacked client that you are not <div className='code'>100%</div> sure is safe. This page is also in <div className='code'>development</div>, meaning features are prone to break! So be careful!!!</div> <div className='code'>Sponsored clients</div> <h1>None XD</h1> <div className='code'>Submitted clients</div> {client // 仅使用提交后的filterParams做过滤 .filter((clientItem) => { // 未点击搜索时默认展示所有客户端 if (!filterParams) return true; // 匹配客户端名称(如果填了搜索词) if (filterParams.searchname && clientItem.name !== filterParams.searchname) return false; // 匹配价格 if (clientItem.price !== filterParams.price) return false; // 匹配安全状态 if (!clientItem.safe.includes(filterParams.safe)) return false; // 匹配MC版本 if (!clientItem.mcversion.includes(filterParams.mcver)) return false; // 匹配客户端类型 if (clientItem.type !== filterParams.type) return false; // 匹配兼容性 if (!clientItem.compat.includes(filterParams.compatibility)) return false; return true; }) .map((client, index) => { return ( <Client key={index} safestatus={client.safestatus} safe={client.safe} name={client.name} price={client.price} mcversion={client.mcversion} type={client.type} compat={client.compat} desc={client.desc} screen={client.screen} download={client.download} /> ); })} </div> </body> ); } export default App;
额外优化说明
- 如果你需要模糊匹配名称,可以把名称匹配的逻辑改成
clientItem.name.toLowerCase().includes(filterParams.searchname.toLowerCase()),输入部分关键词就能搜到对应客户端 - 代码里补了所有下拉选的双向绑定,原来的下拉选选中值不会被记录的问题也同步修复了
- 给map渲染的Client组件加了key属性,避免React控制台报错
内容的提问来源于stack exchange,提问作者user15011471
相关产品推荐
相关产品推荐

