我正在学习反应,并尝试在动态获取请求中使用文本输入
我的组件定义为。。。
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>
);
};