ReactJS实现回车键触发搜索按钮功能问题咨询
解决React中表单回车刷新页面,触发搜索按钮操作的问题
我来帮你搞定这个问题!你现在遇到的情况是:在搜索框按下回车键时,页面会直接刷新,而不是执行和点击搜索按钮一样的图片搜索操作,而且表单和搜索按钮还是两个独立的组件。下面是具体的解决方案,我们按照React的最佳实践来调整代码:
核心思路
- 首先要阻止表单的默认提交行为,避免浏览器自动刷新页面
- 把搜索逻辑统一放到父组件(App)中,这样表单提交和按钮点击都能调用同一个搜索方法,更符合React单向数据流的原则
- 子组件(Button2)只负责渲染按钮和加载状态,触发父组件的搜索方法就好
具体修改步骤
1. 调整父组件(App.js)
我们需要把Button2里的搜索逻辑移到App组件中,给表单添加提交事件,并绑定搜索方法:
import React, { Component } from 'react'; import './App.css'; import { FormGroup, FormControl, InputGroup, Form, } from 'react-bootstrap' import Conditional from './conditional' import Button2 from './button.js' const $ = require('cheerio'); // 统一移到顶部引入 class App extends Component{ constructor(props){ super(props) this.state = { isLoading: true, isLoading2: true, query: '', fimg: [], } this.isloaded = this.isLoaded.bind(this) this.handleSearch = this.handleSearch.bind(this) // 绑定搜索方法 } isLoaded = () => { this.setState({ isLoading: !this.state.isLoading, isLoading2: false }) } fimgSet = fimgData => { this.setState({ fimg: fimgData }); } // 新增搜索方法,原Button2里的搜索逻辑移到这里 handleSearch(){ this.isLoaded(); const BASE_URL = 'https://cors-anywhere.herokuapp.com/https://www.zerochan.net/' const DYM_URL = `${BASE_URL}${this.state.query}?s=fav` let headers = new Headers({ 'Accept' : "text/plain", 'Content-Type': "text/plain", 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Mobile Safari/537.36' }); fetch(DYM_URL, { method: "GET", mode: "cors", cache: "no-cache", credentials: 'same-origin', headers: headers, // 修正原代码的笔误:header改为headers }) .then(res => res.text()) .then(body => { const imgUrls = []; const imgLen = $('p > a', body).length; for (let i = 0; i < imgLen; i++){ imgUrls[i]=($('p > a', body)[i].attribs.href); } const regex = /https:\/\/static.zerochan.net.+.(jpg|png)/ const match = imgUrls.filter(value => regex.test(value)); this.fimgSet(match); this.isLoaded(); }) .catch(function(err){ console.log(err); this.isLoaded(); // 出错后也要恢复加载状态,避免一直显示loading }.bind(this)); } render(){ return( <div className="App"> <div className="App-title"> <span className="bg-title"> Anime Image Gallery </span></div> <div className="app-mini-title"> <span className="bg-title">Enter the name of an Anime series</span></div> {/* 给表单添加onSubmit事件,阻止默认刷新并触发搜索 */} <Form className="OutterformSize" onSubmit={(e) => { e.preventDefault(); // 关键:阻止表单默认提交行为,避免页面刷新 this.handleSearch(); // 执行搜索逻辑 }}> <FormGroup> <InputGroup className="formSize"> <FormControl size="lg" type="text" placeholder="Try Searching Pokémon, DRAGON+BALL or Wallpaper" value = {this.state.query} onChange= {event => {this.setState({query: event.target.value})}} /> </InputGroup> </FormGroup> {/* 把搜索方法传递给Button2组件 */} <Button2 isLoading={this.state.isLoading} isLoaded={this.isLoaded} onSearch={this.handleSearch} /> </Form> <div> <Conditional images={this.state.fimg} isLoading2={this.state.isLoading2}/> </div> </div> ) } } export default App;
2. 简化子组件(Button2.js)
现在Button2不需要处理搜索逻辑了,只负责渲染按钮和加载状态,点击时调用父组件传过来的方法:
import React from "react"; import Spinner from 'react-bootstrap/Spinner'; import { ButtonToolbar } from "react-bootstrap"; import Button from 'react-bootstrap/Button' class Button2 extends React.Component{ render(){ if (this.props.isLoading === false){ return( <div> <ButtonToolbar className="text-center d-block"> <Button variant="primary"> <Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" /> Loading </Button> </ButtonToolbar> </div> )} else { return( <div> <ButtonToolbar className="text-center d-block"> {/* 点击按钮调用父组件的搜索方法 */} <Button variant="primary" type="submit" onClick={() => this.props.onSearch()}>Search</Button> </ButtonToolbar> </div> )} } } export default Button2;
为什么要这么改?
- 阻止默认行为:表单默认的提交行为会导致页面刷新,用
e.preventDefault()就能直接避免这个问题 - 统一逻辑:把搜索逻辑放到父组件,让表单和按钮共享同一个方法,不仅符合React的设计理念,也方便后续维护和修改
- 松耦合:子组件只负责UI,不处理业务逻辑,这样组件之间的依赖更少,更灵活
修改完成后,不管是点击搜索按钮,还是在输入框按下回车键,都会执行图片搜索操作,页面也不会再刷新啦!
内容的提问来源于stack exchange,提问作者VickTree
相关产品推荐
相关产品推荐

