使用来自先前输入的数据反应表单

Posted

技术标签:

【中文标题】使用来自先前输入的数据反应表单【英文标题】:React form using data from previous input 【发布时间】:2021-09-10 06:05:39 【问题描述】:

我正在使用 react 和一个天气 API,并将这个表单放在一起:

function Forecast() 
  const [cities, setCities] = React.useState([]);

  const addCity = (city) => 
    if (!city.text || /^\s*$/.test(city.text)) 
      return;
    

    const newCities = [city, ...cities];

    setCities(newCities);
  ;

  const removeCity = (id) => 
    const removedArray = [...cities].filter((city) => city.id !== id);

    setCities(removedArray);
  ;

  return (
    <div>
      <Form onSubmit=addCity />
    </div>
  );


const Form = (props) => 
  const api = 
    key: "39471307bd579e5ce6b1d89dc164dd77",
    base: "https://api.openweathermap.org/data/2.5/",
  ;

  const [input, setInput] = React.useState("");
  const [weather, setWeather] = React.useState();
  const [query, setQuery] = React.useState("");

  const handleChange = (e) => 
    setInput(e.target.value);
  ;

  const handleSubmit = (e) => 
    e.preventDefault();

    fetch(`$api.baseweather?q=$input&appid=$api.key&units=metric`)
      .then((res) => res.json())
      .then((result) => setWeather(result));

    props.onSubmit(
      id: Math.floor(Math.random() * 10000),
      text: input,
      data: weather,
    );

    setInput("");
  ;

  return (
    <form className="search-container" onSubmit=handleSubmit>
      <input
        type="text"
        placeholder="Enter City"
        name="text"
        value=input
        className="search"
        onChange=handleChange
      />
      <button className="add-card-button">
        <i className="fas fa-plus-circle"></i>
      </button>
    </form>
  );
;

ReactDOM.render(<Forecast />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

当我对此进行测试时,第一次搜索城市时它不会返回任何数据,而第二次搜索时,它会使用第一次搜索的输入,依此类推。有谁知道我怎样才能得到它,以便第一次搜索立即返回数据?

【问题讨论】:

【参考方案1】:

fetch()异步的。您必须在 API 调用完成后设置天气数据。

此外,您必须确保使用新的result(调用setWeather(result) 不会立即更新weather)。

handleSubmit 编辑成如下内容:

  const handleSubmit = (e) => 
    e.preventDefault();

    fetch(`$api.baseweather?q=$input&appid=$api.key&units=metric`)
      .then((res) => res.json())
      .then((result) => 
        props.onSubmit(
          id: Math.floor(Math.random() * 10000),
          text: input,
          data: result,
        );
        setWeather(result);
        setInput("");
      );
  ;

资源:

How to return the response from an asynchronous call? useState set method not reflecting change immediately

完整代码:

function Forecast() 
  const [cities, setCities] = React.useState([]);

  const addCity = (city) => 
    if (!city.text || /^\s*$/.test(city.text)) 
      return;
    

    const newCities = [city, ...cities];
    console.log(newCities);
    setCities(newCities);
  ;

  const removeCity = (id) => 
    const removedArray = [...cities].filter((city) => city.id !== id);

    setCities(removedArray);
  ;

  return (
    <div>
      <Form onSubmit=addCity />
    </div>
  );


const Form = (props) => 
  const api = 
    key: "39471307bd579e5ce6b1d89dc164dd77",
    base: "https://api.openweathermap.org/data/2.5/",
  ;

  const [input, setInput] = React.useState("");
  const [weather, setWeather] = React.useState();
  const [query, setQuery] = React.useState("");

  const handleChange = (e) => 
    setInput(e.target.value);
  ;

  const handleSubmit = (e) => 
    e.preventDefault();

    fetch(`$api.baseweather?q=$input&appid=$api.key&units=metric`)
      .then((res) => res.json())
      .then((result) => 
        props.onSubmit(
          id: Math.floor(Math.random() * 10000),
          text: input,
          data: result,
        );
        setWeather(result);
        setInput("");
      );
  ;

  return (
    <form className="search-container" onSubmit=handleSubmit>
      <input
        type="text"
        placeholder="Enter City"
        name="text"
        value=input
        className="search"
        onChange=handleChange
      />
      <button className="add-card-button">
        <i className="fas fa-plus-circle"></i>
      </button>
    </form>
  );
;

ReactDOM.render(<Forecast />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

【讨论】:

【参考方案2】:

useRef 钩子适用于表单。为表单分配一个 useRef 挂钩变量

删除!!

  const [input, setInput] = React.useState("");

替换

const input = useRef('')

输入标签

 <input
    type="text"
    placeholder="Enter City"
    name="text"
    ref=input
    className="search"
  />

提交函数

  const handleSubmit = (e) => 
e.preventDefault();

fetch(`$api.baseweather?q=$input.current.value&appid=$api.key&units=metric`)
  .then((res) => res.json())
  .then((result) => setWeather(result));

props.onSubmit(
  id: Math.floor(Math.random() * 10000),
  text: input.current.value,
  data: weather,
);

input.current.value = '';

;

【讨论】:

你刚刚用一个 ref 替换了一个正常的状态变量,这完全没有解决任何问题。你还没有解释你的方法。您的代码块没有正确缩进。【参考方案3】:

我现在不会编码。但是尝试将 fetch 放在 useEffect 挂钩中。并在提交后以某种方式触发效果。里面有条件或其他东西。也许将状态作为 useEffect 的依赖项传递。

也许明天我可以为您的代码发送适当的建议

【讨论】:

这不是问题所在。 handleSubmit()(和 fetch() 依次)确实在提交表单时被调用。

以上是关于使用来自先前输入的数据反应表单的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs +如何在指令中获取先前的输入字段值

保留文本框的先前值,直到表单关闭

根据先前在同一表单上输入的值自动完成表单字段

angular 7 反应式表单:为表单中的每个输入字段动态添加/删除输入字段

模型输入必须来自 `tf.keras.Input` ...,它们不能是先前非输入层的输出

无法编辑文本输入反应 redux 表单