防止在键入时重新呈现主菜单

Prevent rerender home menu while typing

我的搜索栏组件有问题。执行搜索时,请求成功并且我们得到了所需的显示,但是如果我们想对其进行新的搜索,我们会在键入时自动 return 到主菜单。你能告诉我如何在没有returning 的情况下保持之前搜索的显示吗?提前谢谢你

import React, {Component} from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'

class App extends Component {
    constructor(props) {
        super(props)
        this.state = {
            pokemon: '',
            resultDatas : '',
            search: false,
            whiteList: [],
            error:''
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleClick = this.handleClick.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
        this.fillWhiteList()
    }

    //white list function to forbid all special characters
    fillWhiteList() {
        axios.get('https://pokeapi.co/api/v2/pokemon/')
        .then(list => {
            const resultList =  list.data.results
            const theList = resultList.map(theList => theList.name.toLowerCase())
            this.setState({
                whiteList: theList
            })
        })
    }

    //handle the value of the text field and keep letter in lower case
    //deletion of white space in typing to not generate errors
    //async to have the last letter of the value
    handleChange = async function(e) {
        await this.setState({
            pokemon: e.target.value.toLowerCase().trim(),
            resultDatas:''
        })
    }

    //Call API function and data table recovery with 'resultDatas' state
    handleSubmit =  (e) => {
        e.preventDefault()
         axios.get('https://pokeapi.co/api/v2/pokemon/' + this.state.pokemon
        )
        .then( res => {
            console.log(res);
            const response = res.data
            this.onResetField()
            this.setState({
                resultDatas: response,
                search:true,
                error: res.status
            })
            console.log(this.state.error);
        })
    }

    //Home button function
    handleClick() {
        this.setState({
            resultDatas : '',
            search: false,
            pokemon: ''
        })
    }

    //clear input function when onClick in the cross icon
    onResetField() {
        const iconReset = document.querySelector('input')
        iconReset.value = ''
    }

    render(){
        // Home page display when no value is submitted
        if (this.state.search === false || this.state.resultDatas === '') {
            return (
                <div>
                    <SearchBar
                        value={this.handleChange}
                        submit={this.handleSubmit}
                        placeholder="Search Pokemon"
                        />
                    <Global
                        loading="Loading..."
                    />
                </div>
            )
            //Error display
        }else if (!this.state.whiteList.includes(this.state.pokemon) || this.state.error !== 200) {
           return(
               <div>
                   <SearchBar
                       submit={this.handleSubmit}
                       value={this.handleChange}
                       placeholder="Search Pokemon"
                   />
                   <Error
                        wrong="Pokemon not found please retry"
                   />
                   <PreviousButton
                        previously={this.handleClick}
                        return="Back to menu"
                   />
               </div>
           )
            // pokemon display
        }else {
            return(
                <div>
                    <SearchBar
                        submit={this.handleSubmit}
                        value={this.handleChange}
                        placeholder="Search Pokemon"
                    />
                        <PreviousButton
                            previously={this.handleClick}
                            return="Back to menu"
                        />
                    <ItemList
                        list={this.state.resultDatas}
                    />
                </div>
            )
        }
    }
}

//homepage display
class Global extends Component {
    constructor() {
       super()
       this.state = {
           item:[],
           isLoaded:false
       }
    }

       //Api call for display  home page
        APICall() {
           axios.get('https://pokeapi.co/api/v2/pokemon/venusaur')
           .then(response => {

               this.setState({
                   item: response,
                   isLoaded:true
               })
           })
       }

   render() {
       // loading display if request not found
           if (!this.state.isLoaded) {
           return (
               <div>
                    <div>{this.props.loading}</div>
               </div>
          )
       }else {
           return(
               <div>
                    {this.state.item.name}
               </div>
           )
       }
   }
}

//Searchbar component
 class SearchBar extends Component{
    render(){
        return(
            <form onSubmit={this.props.submit} autoSave="off">
                <input
                    inputMode="tel"
                    required="required"
                    autoComplete="off"
                    type="text"
                    onChange={this.props.value}
                    id="searchbar"
                    placeholder={this.props.placeholder}
                />
            </form>
        )
    }
}

//list of Pokemon component

class ItemList extends Component{
    render(){
        return(
            <div>
                {this.props.list.name}
                <img src={this.props.list.sprites.front_default}  alt="pokemon"/>
            </div>
        )
    }
}

// Previous button component
 class PreviousButton extends Component{

    render(){
        return(
            <button onClick={this.props.previously}>{this.props.return}</button>
        )
    }
}

//error page component
 class Error extends Component{
    render(){
        return(
            <div>
                {this.props.wrong}
            </div>
        )
    }
}

ReactDOM.render(<App/>, document.querySelector('#root'))

这里有一个 codesandbox,以防它不起作用 https://codesandbox.io/s/keen-ritchie-t5kn8?file=/src/index.js

看来这是导致问题的原因。

//handle the value of the text field and keep letter in lower case
//deletion of white space in typing to not generate errors
//async to have the last letter of the value
handleChange = async function(e) {
    await this.setState({
        pokemon: e.target.value.toLowerCase().trim(),
        resultDatas:''
    })
}

当您处理输入值更改时,您将 resultDatas 设置为空字符串。在您的呈现函数中,您的“主页”正在检查 search 是否等于 false 或者您的 resultDatas 是否为空字符串,因此一旦您开始输入新的搜索,它就会重置 resultData 并将您带到主页.

 if (this.state.search === false || this.state.resultDatas === '') {
    return (
        <div>
            <SearchBar
                value={this.handleChange}
                submit={this.handleSubmit}
                placeholder="Search Pokemon"
            />
            <Global
                loading="Loading..."
            />
        </div>
    )
}

要解决此问题,您可以将其设置为不会像这样自动清除您的结果数据

handleChange = function(e) {
    this.setState({
        pokemon: e.target.value.toLowerCase().trim()
    })
}

**我从这个函数中删除了 async/await 关键字,因为 this.setState 是回调,而不是承诺。

CodeSandbox 有变化:https://codesandbox.io/s/crazy-rgb-lwzne?file=/src/index.js

附加信息

如果您不想立即被定向到您的错误页面,那么您将需要跟踪您搜索的当前口袋妖怪,与输入的当前值分开。我已经更新了我的 CodeSandbox上面包括这些额外的变化。

如果您查看 CodeSandbox,您会发现您的状态中现在有一个 currentPokemon 值。在您设置状态的提交函数内部,我将更新 currentPokemon 使其等于 this.state.pokemon。将它们组合在一起的最后一部分是在渲染函数中。您需要更改错误页面条件以检查您的白名单是否包含 this.state.currentPokemon 而不是 this.state.pokemon.

您应该使用 search 而不是 resultDatas 来指示搜索框状态

handleChange = async function(e) {
    await this.setState({
        pokemon: e.target.value.toLowerCase().trim(),
         search:false
    })
}

然后

 render(){
        // Home page display when no value is submitted
       
            return (
                <div>
                    <SearchBar
                        value={this.handleChange}
                        submit={this.handleSubmit}
                        placeholder="Search Pokemon"
                        />
                   {!this.state.search  && <Global
                        loading="Loading..."
                    />}

                   {this.state.resultDatas && <ItemList
                        list={this.state.resultDatas}
                    />} 

                  .
                  .
                  .

                </div>
            )
       
        
    }
}