onChange和setState在我的代码中无法一起使用

时间:2019-06-09 03:06:34

标签: javascript reactjs algolia react-instantsearch

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

这是调用搜索框组件的类

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,它工作正常,它会相应地打印出open和close。但是,一旦启用setState,输入框就根本不允许我输入任何内容。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您的代码编写不正确。 connectSearchBox用于将组件连接到Algolia api。这是对组件定义的一次性设置。它返回一个高阶组件,该组件使用api功能包装给定的组件。您可以查看源代码here。通过将自定义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}
        />

docs中的用法示例。我认为您想要实现的是将props向下传递到组件,但是connectSearchBox已经保证您传递给HOC的任何props也将传递给您的自定义搜索框。 Line 335