
本文旨在解决 React 应用中,父组件向子组件传递参数后,子组件未能根据新的参数值及时更新数据的问题。通过分析问题代码,我们将定位到表单提交导致的页面刷新是罪魁祸首,并提供使用 e.preventDefault() 阻止默认行为的解决方案,确保组件能够正确响应参数变化并刷新数据。
在 React 应用开发中,父子组件之间的数据传递是常见的模式。然而,有时我们可能会遇到这样的问题:父组件传递给子组件的参数发生了变化,但子组件并没有根据新的参数值重新渲染或获取数据。这会导致 UI 显示的数据与预期不符,影响用户体验。
下面我们通过一个实际案例来分析这个问题,并提供解决方案。
一个应用包含一个搜索栏(Navbar)和一个数据表格(AttacksGrid)。用户在搜索栏中输入关键词,点击搜索按钮后,关键词会被传递给 AttacksGrid 组件,AttacksGrid 组件会根据关键词从后端获取数据并显示在表格中。
然而,实际情况是,每次点击搜索按钮后,AttacksGrid 组件都会显示空数据,或者显示初始状态的数据,并没有根据新的关键词进行数据刷新。
以下是相关组件的代码:
App 组件:
function App() {
const [query, setQuery] = useState("");
const searchClicked = (keyword) => {
console.log(`setting query to: ${keyword}`);
setQuery(keyword); // for now we want to search for the keyword in the name and description, platform is not supported yet
};
return (
<div>
<Navbar onSearchClicked={searchClicked} />
<AttacksGrid query={query} />;
</div>
);
}AttacksGrid 组件:
function AttacksGrid({ query }) {
console.log(`QUERY IS ${query}`);
useEffect(() => {
fetch(`http://127.0.0.1:9000/attacks?name=${query}&description=${query}`)
.then((response) => response.json())
.then((data) => {
console.log(data);
setAttacks(data);
})
.catch((err) => console.log(err));
}, [query]);
const [attacks, setAttacks] = useState([]);
return (
<>
<table className="table table-dark">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Platforms</th>
<th scope="col">Detection</th>
<th scope="col">Phase</th>
</tr>
</thead>
{attacks.map((attack) => (
<tbody key={attack.ID}>
<tr>
<th scope="row">{attack.NAME}</th>
<td>{attack.DESCRIPTION}</td>
<td>{attack.X_MITRE_PLATFORMS}</td>
<td>{attack.X_MITRE_DETECTION}</td>
<td>{attack.PHASE_NAME}</td>
</tr>
</tbody>
))}
</table>
</>
);
}Navbar 组件:
function Navbar({ onSearchClicked }) {
const [message, setMessage] = useState("");
const handleChange = (event) => {
setMessage(event.target.value);
console.log(message);
};
return (
<nav className="navbar bg-body-tertiary">
<div className="container-fluid">
<form className="d-flex" role="search">
<input
id="message"
name="message"
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
onChange={handleChange}
/>
<button
className="btn btn-outline-success"
type="submit"
onClick={() => {
onSearchClicked(message);
}}
>
Search
</button>
</form>
</div>
</nav>
);
}通过观察代码,我们发现 AttacksGrid 组件的 useEffect 依赖于 query 变量,当 query 发生变化时,useEffect 应该重新执行,从而从后端获取新的数据。
问题出在 Navbar 组件中的表单提交。当点击搜索按钮时,由于 button 的 type 属性为 submit,表单会默认提交,导致页面刷新。页面刷新后,App 组件的状态会被重置,query 重新变为空字符串,因此 AttacksGrid 组件总是显示初始状态的数据。
要解决这个问题,我们需要阻止表单的默认提交行为。可以使用 e.preventDefault() 方法来实现。
修改 Navbar 组件中的 button 的 onClick 事件处理函数:
<button
className="btn btn-outline-success"
type="submit"
onClick={(e) => {
e.preventDefault(); //Preventing default page refresh submit form action
onSearchClicked(message);
}}
>
Search
</button>通过在 onClick 事件处理函数中调用 e.preventDefault(),我们可以阻止表单的默认提交行为,从而避免页面刷新。
以下是修改后的 Navbar 组件的完整代码:
function Navbar({ onSearchClicked }) {
const [message, setMessage] = useState("");
const handleChange = (event) => {
setMessage(event.target.value);
console.log(message);
};
return (
<nav className="navbar bg-body-tertiary">
<div className="container-fluid">
<form className="d-flex" role="search">
<input
id="message"
name="message"
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
onChange={handleChange}
/>
<button
className="btn btn-outline-success"
type="submit"
onClick={(e) => {
e.preventDefault(); //Preventing default page refresh submit form action
onSearchClicked(message);
}}
>
Search
</button>
</form>
</div>
</nav>
);
}在 React 应用中,如果子组件未能根据父组件传递的参数及时更新数据,需要检查以下几点:
通过使用 e.preventDefault() 阻止表单的默认提交行为,我们可以避免页面刷新,确保组件能够正确响应参数变化并刷新数据.
以上就是React 组件参数未更新导致数据未刷新问题的解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号