【问题标题】:SetState Not Updating to fetch dynmicallySetState 未更新以动态获取
【发布时间】:2020-07-23 22:52:51
【问题描述】:

我正在学习反应,我正在尝试在动态获取请求中使用文本输入

我的组件被定义为...

export default testpage = () => {
    const [state, setState] = React.useState({})
    let handleChange = (event) => {
            setState({input: event.target.value})
          }
    async function buttonClick (input) {
    console.log(state.input)
      await fetch(`http://localhost:8080/api/${input}`)
      .then(response => response.json())
        .then(data => setState({...state, data}))
 
render(
      <input type={'text'} onChange={handleChange.bind(this)} />
      <Button onClick={() => buttonClick(state.input)}>test</Button>
      )
   }

我的问题与 useState 异步更新有关。如果我输入一个数字,即。 4 进入输入框,然后点击按钮。我第一次单击按钮时,由于状态尚未更新,未定义被传递给 fetch 语句,因此获取失败。如果我再次单击该按钮,则获取成功。我已经阅读了 useEffect 钩子,但我无法弄清楚如何将它应用到我的情况。

【问题讨论】:

标签: javascript reactjs react-native react-redux react-hooks


【解决方案1】:

更改代码以将输入的值直接保持在状态中。 state value not need to be an object - 它可以是一个字符串、数字或null,如果这就是你所需要的。

const TestPage = () => {
  const [postId, setPostId] = useState(null);

  async function buttonClick() {
    await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}/comments`)
      .then(response => response.json())
      .then(data => console.log(data));
  }

  return (
    <div>
      <input onChange={e => setPostId(e.target.value)} />
      <button onClick={buttonClick}>test</button>
    </div>
  );
};

组件已按预期工作 - 它会在每次单击按钮时下载数据。它需要显示逻辑和适当的错误处理,但为了清楚起见,我将其保留。


您提到了useEffect,下面是如何使用它的示例:

function Test() {
  const [postId, setPostId] = useState(null);
  const [data, setData] = useState([]);

  useEffect(() => {
    async function getComments() {
      if (Number(postId)) {
        await fetch(
            `https://jsonplaceholder.typicode.com/posts/${postId}/comments`
          )
          .then(response => response.json())
          .then(data => setData(data));
      } else { setData([]); }
    }

    getComments();
  }, [postId]);

  const comments = data
    ? data.map(comment => <li key={comment.id}>{comment.body}</li>)
    : [];

  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      <input type={"text"} onChange={e => setPostId(e.target.value)} />
      {comments.length > 0 ? <ul>{comments}</ul> : <span>Write correct post ID (number 1-100)</span>}
    </div>
  );
}

但是useEffect 改变了您与组件的交互方式。它在渲染新状态后运行效果,这意味着它在更改输入值后立即运行。也就是说,你根本不需要&lt;button&gt;

因为您在按钮单击时开始请求,所以最好使用useCallback 挂钩。只要postId(输入的值)没有改变,它就会在每次单击按钮时返回相同的函数。您可以像在第一个示例中使用 buttonClick 一样使用此功能:

const TestPage = () => {
  const [postId, setPostId] = useState(null);

  const handleClick = useCallback(() => {
    async function getData() {
      await fetch(
        `https://jsonplaceholder.typicode.com/posts/${postId}/comments`
      )
        .then(response => response.json())
        .then(data => console.log(data));
    }

    getData();
  }, [postId]);

  return (
    <div>
      <input onChange={e => setPostId(e.target.value)} />
      <button onClick={handleClick}>test</button>
    </div>
  );
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多