
本文旨在解决 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 (
;
);
}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 (
<>
| Name | Description | Platforms | Detection | Phase |
|---|---|---|---|---|
| {attack.NAME} | {attack.DESCRIPTION} | {attack.X_MITRE_PLATFORMS} | {attack.X_MITRE_DETECTION} | {attack.PHASE_NAME} |
Navbar 组件:
function Navbar({ onSearchClicked }) {
const [message, setMessage] = useState("");
const handleChange = (event) => {
setMessage(event.target.value);
console.log(message);
};
return (
);
}通过观察代码,我们发现 AttacksGrid 组件的 useEffect 依赖于 query 变量,当 query 发生变化时,useEffect 应该重新执行,从而从后端获取新的数据。
问题出在 Navbar 组件中的表单提交。当点击搜索按钮时,由于 button 的 type 属性为 submit,表单会默认提交,导致页面刷新。页面刷新后,App 组件的状态会被重置,query 重新变为空字符串,因此 AttacksGrid 组件总是显示初始状态的数据。
解决方案
要解决这个问题,我们需要阻止表单的默认提交行为。可以使用 e.preventDefault() 方法来实现。
修改 Navbar 组件中的 button 的 onClick 事件处理函数:
通过在 onClick 事件处理函数中调用 e.preventDefault(),我们可以阻止表单的默认提交行为,从而避免页面刷新。
完整代码
以下是修改后的 Navbar 组件的完整代码:
function Navbar({ onSearchClicked }) {
const [message, setMessage] = useState("");
const handleChange = (event) => {
setMessage(event.target.value);
console.log(message);
};
return (
);
}总结
在 React 应用中,如果子组件未能根据父组件传递的参数及时更新数据,需要检查以下几点:
- 父组件是否正确地更新了状态。
- 子组件的 useEffect 是否正确地依赖于父组件传递的参数。
- 是否存在表单提交或其他导致页面刷新的操作。
通过使用 e.preventDefault() 阻止表单的默认提交行为,我们可以避免页面刷新,确保组件能够正确响应参数变化并刷新数据.










