如何从React子组件更新父组件状态?附组件重构方案
问题描述
我在React页面中写了这段代码:
<a data-tab="settings" onClick={() => this.setState({ active_tab: "settings" }) } > <i style={{ backgroundImage: "url(/icons/settings.svg)" }} /> <span>To settings</span> </a>
想知道怎么把这段代码重构为组件,以及如何通过该组件更新父组件的本地状态。
一、基于类组件的实现
组件文件(MyButton.js)
import React, { Component } from "react"; class MyButton extends Component { constructor(props) { super(props); this.state = { tab: props.tab, icon: props.icon, label: props.label, }; } render() { return ( <div> <button onClick={() => this.props.updateActiveTab(this.state.tab)} data-tab={this.state.tab} > <i style={{ backgroundImage: `url(${this.state.icon})` }} /> <span> { this.state.label } </span> </button> </div> ) } }; export default MyButton;
父组件(React页面)
import MyButton from "../components/MyButton/"; class MyReactPage extends Component { updateActiveTab = value => { this.setState({ active_tab: value }); } render() { return ( <> <MyButton updateActiveTab={this.updateActiveTab} tab="settings" icon="/icons/settings.svg" label="To settings" /> </> ) } }
二、基于React Hooks的实现及错误修正
原Hooks方案存在两个错误:
- Invalid hook call. Hooks can only be called inside of the body of a function component. → 钩子调用无效。钩子只能在函数组件的主体内部调用。
- 'active_tab' is declared but its value is never read. → 'active_tab'已声明但从未被使用。
错误原因及修正后的代码
- 原组件接收props的方式错误,函数组件的props是一个整体对象,需通过解构或
props.xxx获取; - 子组件无需维护
active_tab状态,应通过父组件传入的回调函数更新父组件状态; - 父组件调用函数组件的方式错误,需用
<MyButton />标签形式,而非直接调用函数。
修正后的组件文件(MyButton.js)
import React from "react"; const MyButton = (props) => { const { tab, icon, label, onTabChange } = props; return ( <button data-tab={tab} onClick={() => onTabChange(tab)} > <i style={{ backgroundImage: `url(${icon})` }} /> <span> { label } </span> </button> ); }; export default MyButton;
修正后的类父组件(React页面)
import React, { Component } from "react"; import MyButton from "../components/MyButton/"; class MyReactPage extends Component { updateActiveTab = value => { this.setState({ active_tab: value }); } render() { return ( <> <MyButton onTabChange={this.updateActiveTab} tab="settings" icon="/icons/settings.svg" label="To settings" /> </> ) } }
父组件也用Hooks实现的版本
import React, { useState } from "react"; import MyButton from "../components/MyButton/"; const MyReactPage = () => { const [activeTab, setActiveTab] = useState(""); const handleTabChange = (tabValue) => { setActiveTab(tabValue); }; return ( <> <MyButton onTabChange={handleTabChange} tab="settings" icon="/icons/settings.svg" label="To settings" /> </> ) }
内容的提问来源于stack exchange,提问作者Marty
相关产品推荐
相关产品推荐

