设置状态未更新以动态获取



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

我的组件定义为。。。

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失败,因为未定义被传递到fetch语句,因为状态尚未更新。如果我第二次点击按钮获取成功。我已经阅读了useEffect挂钩,但我不知道如何将其应用于我的情况。

更改代码以使输入的值直接处于状态。状态值不需要是一个对象,它可以是字符串、数字或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会改变您与组件的交互方式。它在呈现新状态后运行效果,这意味着它在更改输入值后立即运行。也就是说,你根本不需要<button>

因为您开始请求按钮点击,所以最好使用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>
  );
};

相关内容

  • 没有找到相关文章

最新更新