【问题标题】:Prevent rerender home menu while typing键入时防止重新呈现主菜单
【发布时间】:2020-11-04 08:07:15
【问题描述】:

我的搜索栏组件有问题。执行搜索时,请求成功并且我们得到了所需的显示,但是如果我们想对其进行新的搜索,我们会在输入过程中自动返回主菜单。你能告诉我如何保持以前搜索的显示而不返回吗?提前谢谢你

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'))

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

【问题讨论】:

  • 您能创建一个代码框来重现您的问题吗?或者查看发布的代码?我试图用你发布的一段代码来重现,但做不到。例如,您的&lt;SearchBar&gt; 组件引用了this.props,但它没有任何props...
  • 哦,是的,抱歉,这里是密码框codesandbox.io/s/keen-ritchie-t5kn8?file=/src/index.js 我也会编辑我的帖子

标签: javascript reactjs state searchbar


【解决方案1】:

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

//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 是一个回调,而不是一个承诺。

有变化的代码沙盒:https://codesandbox.io/s/crazy-rgb-lwzne?file=/src/index.js

其他信息

如果您不想立即被定向到错误页面,那么您将需要跟踪您搜索的当前 pokemon 与正在输入的当前值分开。我已将上面的 CodeSandbox 更新为包括这些额外的更改。

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

【讨论】:

  • 感谢您的快速回复。空字符串 ``` resultDatas``` 是我找到的方式,因此通过键入新的搜索,显示不会自动生成错误显示。我想在用户在字段中键入新搜索时保持搜索显示,而在提交表单之前不改变显示。例如,如果您输入“bulbasaur”,subit 并输入一个新的搜索,我希望bulbasaur 的显示一直保持到下一次提交。
  • 我已经用其他信息更新了我的答案。我还更新了 CodeSandbox 以显示所需的更改。
  • 这完全有效!非常感谢克里斯,这是我非常想要的行为,感谢您的解释,我更了解问题出在哪里
  • @EdwinLandsfield 没问题!
【解决方案2】:

您应该使用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>
            )
       
        
    }
}

【讨论】:

    猜你喜欢
    • 2020-05-16
    • 1970-01-01
    • 2016-01-27
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多