首页 > 解决方案 > onChange 和 setState 在我的代码中不能一起工作

问题描述

我正在尝试构建一个搜索框。但是,当我想在输入内容时设置状态时,该框根本不允许我输入任何内容。

这是调用搜索框组件的类

export default class Tagsearch extends Component {

  constructor(props) {
    super(props);

    this.state = {
      hitsDisplay:false,
      inputContent:"",
      tags:[]
    };
  }
  openDisplay = () => {
    console.log("open")
    // this.setState({ hitsDisplay: true })
  }

  closeDisplay = () => {
    console.log("close")
    // this.setState({ hitsDisplay: false })
  }

  render() {

    let inputTags = (
      this.state.tags.map((tag, i) => 
        <li key={i} style={styles.items}>
          {tag}
          <button onClick={() => this.handleRemoveItem(i)}>
            (x)
          </button>
        </li>
      )
    )

    let result = (
      <div className="container-fluid" id="results">

      </div>
    )

    if (this.state.hitsDisplay) {
      result = (
        <div className="container-fluid" id="results">
          <div className="rows">
            <MyHits handleSelect={this.handleSelect}/>
          </div>

          <div className="rows">
            <Pagination />
          </div>
        </div>
      )
    }

    return (
      <InstantSearch
        appId="*******"
        apiKey="***********************"
        indexName="tags"
      >
        {inputTags}
        <SearchBox  
          connectSearchBox={connectSearchBox}
          openDisplay={this.openDisplay}
          closeDisplay={this.closeDisplay}
        />
        {result}

      </InstantSearch>
    )
  }
}

以下是搜索框组件

const SearchBox = props => {

  let { 
    connectSearchBox,
    openDisplay,
    closeDisplay
  } = props;

  const CustomSearchBox = connectSearchBox(({ currentRefinement, refine }) => {
    const handleChange = (e, refine) => {
      refine(e.target.value)
      // console.log(e.target.value)
      if (e.target.value !== "") {
        openDisplay();
      } else {
        closeDisplay();
      }
    }

    return (
      <label>
        <ul style={styles.container}>
          <input
            style={styles.input}
            type="text"
            value={currentRefinement}
            onChange={e => handleChange(e, refine)}
          />
        </ul>
      </label>
    )
  })

  return (
    <CustomSearchBox />
  )
}

export default SearchBox;

如果我在 open & closeDisplay 中评论这两个 setState,它工作正常,它会相应地打印出打开和关闭。但是,一旦启用 setState,输入框根本不允许我输入任何内容。

任何帮助表示赞赏。

标签: javascriptreactjsalgoliareact-instantsearch

解决方案


你的代码写错了。connectSearchBox旨在将组件连接到 Algolia api。这是对组件定义的一次性设置。它返回一个用 api 特性包装给定组件的高阶组件。您可以在此处查看源代码。通过将您的自定义 SearchBox 放在 SearchBox 函数中,您将导致组件在每个 render() 循环中重新构建和重新连接,从而不保留状态。这就是为什么一旦您setState的搜索文本消失。

import { connectSearchBox } from 'react-instantsearch-dom';

const CustomSearchBox = ({ currentRefinement, refine, openDisplay, closeDisplay, ...props }) => {
    const handleChange = (e, refine) => {
      refine(e.target.value)
      if (e.target.value !== "")
        openDisplay();
      else
        closeDisplay();
    }

    return (
      <label>
        <ul style={styles.container}>
          <input
            style={styles.input}
            type="text"
            value={currentRefinement}
            onChange={e => handleChange(e, refine)}
          />
        </ul>
      </label>
    )
  })

export default connectSearchBox(CustomSearchBox);

用法

import CustomSearchBox from './CustomSearchBox'
...
       <CustomSearchBox  
          openDisplay={this.openDisplay}
          closeDisplay={this.closeDisplay}
        />

文档中的使用示例。我认为您试图实现的是将道具传递给您的组件,但connectSearchBox已经保证您传递给 HOC 的任何道具也将传递给您的自定义搜索框。335号线


推荐阅读