我在输入的 handleChange 中使用了两个 'setState' 来搜索数组。为什么搜索不安全?

I used two 'setState' inside a handleChange of input, for searching on the array. why the search is unseccesfull?

我有一个城市名称数组。另外,我有一个输入,我希望在数组上搜索任何输入值,同步根据 started[=48] 的城市名称显示输入的占位符=] 与输入值,每当该用户键入一个字符。

cities.json的一部分:

[ 「香港仔」, “阿比林”, “阿克伦”, “奥尔巴尼”, "阿尔伯克基", “亚历山大港”, “阿伦敦”, “阿马里洛”, “阿纳海姆”, “安克雷奇”, “安娜堡”, “安条克”, “苹果谷”, “阿普尔顿”, “阿灵顿”, “阿瓦达”, “阿什维尔”, “雅典”, “亚特兰大”, “大西洋城”, “奥古斯塔”, “极光”, “奥斯汀”, “贝克斯菲尔德”, “巴尔的摩”, “巴恩斯特布尔”, “巴吞鲁日”, “博蒙特”, . . . . . . . . . . . . . . . “威尔明顿”, “温斯顿”, 《冬日天堂》, “伍斯特”, “亚基马”, “扬克斯”, “约克”, 《扬斯敦》 ]

index.jsx:

import React from "react";
import ReactDOM from "react-dom";
import cities from "./cities.json"; //cities is an array.

class App extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            value: '',
            placeholder: ''
        }
    }

    handleChange = (e) => {
        this.setState({
            value: e.target.value
        });
        for (let i = 0; i < cities.length; i++){
            if (cities[i].startsWith(`${this.state.value}`)){
                return this.setState({
                    placeholder: cities[i]
                });
            }
        }
    }


    render() {
        return (
            <div>
                <input value={this.state.value} placeholder={this.state.placeholder} onChange={this.handleChange}/>
            </div>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

但有两个问题:

1- 使用两个 setState: 第二个 setState 是否使用第一个 setState 的结果?

2- 输出不是预期的: 键入的值与占位符值不同步。清除输入时显示占位符(占位符也必须为空)。它也只显示第一个城市,带有任何首字母。例如,如果我输入“Akro”或“Alba”,它会显示“Aberdeen”而不是“Akron”和“Albany”作为占位符。以及如果我输入“Baton”,它会显示“Bakersfield”而不是“Baton Rouge”(注意数组)。

我的输出:

预期输出:

你的解决方案是什么? :)

setState 函数是异步的,所以如果你想使用新状态,你必须向 setState 提供回调并在其中使用新状态。因此,例如,在您的情况下,您必须执行以下操作:

handleChange = (e) => {
    this.setState(
      {
        value: e.target.value
      },
      () => {
        if (this.state.value) {
            for (let i = 0; i < cities.length; i++) {
                if (cities[i].startsWith(this.state.value)) {
                    return this.setState({
                        placeholder: cities[i]
                    });
                }
            }
        }
        return this.setState({ placeholder: ''})
      }
    );
  };

为了正确显示占位符,您需要在渲染中进行以下更改:

render() {
    return (
      <div style={{ position: "relative" }}>
        <input value={this.state.value} style={{ fontFamily: 'Arial', fontSize: 14 }} onChange={this.handleChange} />
        <span style={{ position: "absolute", top: 0, left: 0, padding: '3px 4px', fontSize: 14, fontFamily: 'Arial', opacity: 0.5 }}>
          {this.state.placeholder}
        </span>
      </div>
    );
  }

@Marco Nisi 是正确的,但根据您的问题,您需要锯城建议。 @Arman placeholder 只有在输入框没有值的时候才会显示。但您可以使用 html 中提供的数据列表。请找到 link 到工作解决方案 here

import React from "react";
import cities from "./cities.json"; //cities is an array.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: "",
      placeholder: "",
      suggestions: []
    };
  }

  handleChange = (e) => {
    this.setState(
      {
    value: e.target.value
      },
      () => {
    this.setState(
      {
        suggestions: []
      },
      () => {
        for (let i = 0; i < cities.length; i++) {
          if (cities[i].startsWith(`${this.state.value}`)) {
            this.setState({
              suggestions: [...this.state.suggestions, cities[i]]
            });
          }
        }
      }
    );
      }
    );
  };

  render() {
    return (
      <div>
    <label htmlFor="city">Choose your city:</label>
    <input
      value={this.state.value}
      placeholder={this.state.placeholder}
      onChange={this.handleChange}
      list="suggested_cities"
      name="city"
      id="city"
    />
    <datalist id="suggested_cities">
      {this.state.suggestions.map((suggestion) => {
        return <option value={suggestion} key={suggestion} />;
      })}
    </datalist>
      </div>
    );
  }
}

export default App;

Link 到 fiddle 的工作示例。 https://codesandbox.io/s/react-fiddle-forked-viqmt?from-embed