零经验学 react 的第13天 - 父子组件传值

2 阅读2分钟

一、核心总结

1、向子组件传值

  • 父组件中,在子元素上直接填写属性来传递数据给 子组件, 子组件里可以通过 props 拿到传递过来的数据

2、向父组件传值

  • 子组件中触发 props 上的方法来给父组件传值

二、注意点

  • 读取 props 可以使用解构,如 function Child({name, age}){...}
  • props 可以指定默认值,如 function Child({name, age = 10}){...}
  • 可以使用 <Child {...props} /> 语法来转发所有 props,但不要过度使用
  • <A><B /></A>这样嵌套的JSX, <B/>被视为 <A> 组件的 children 属性
  • 不能直接改变 props,需要交互可以使用 state 进行间接操作

三、代码示例

3.1、父组件向子组件传递数据和函数,子组件通过 props 接收并调用父组件传递的函数来更新父组件的数据,实现父子组件之间的双向数据传递。

// 父组件
import { useState } from "react";
import Child from "./child";

function Parent() {
    const [arr1, setArr1] = useState([
        {id: 1, name: '111'},
        {id: 2, name: '222'},
        {id: 3, name: '333'},
    ]);
    const [arr2, setArr2] = useState([
        {id: 1, name: 'aaa'},
        {id: 2, name: 'bbb'},
        {id: 3, name: 'ccc'},
    ]);
    const [tab, setTab] = useState(1);
    const changeTab = () => {
        setTab(tab === 1 ? 2 : 1);
    }

    // 接收子组件传递的数据
    const setArr = (newArr) => {
        if (tab === 1) {
            setArr1(newArr);
        } else {
            setArr2(newArr);
        }
    }

    return (
        <div className="parent-box">
            <p>parent page</p>
            <div onClick={changeTab} style={{ cursor: 'pointer', display: 'flex', gap: '10px', contentAlign: 'center', justifyContent: 'center' }}>
                <div style={tab === 1 ? {color: '#f00', textDecoration: 'underline'} : {color: '#000'}}>Tab 1 Content</div>
                <div style={tab === 2 ? {color: '#f00', textDecoration: 'underline'} : {color: '#000'}}>Tab 2 Content</div>
            </div>
            
            <div>
                {/* 向子组件传递数据 */}
                <Child arr1={arr1} arr2={arr2} tab={tab} setArr={setArr} />
            </div>
        </div>
    );
}

export default Parent;

3.2、子组件通过 props 接收父组件传递的数据和函数,并在子组件内调用父组件传递的函数来更新父组件的数据,实现父子组件之间的双向数据传递。

// 子组件
import React from "react";

class Child extends React.Component {
    constructor(props) {
        super(props);
        // 接收父组件的数据
        this.state = {
            arr1: props.arr1,
            arr2: props.arr2
        };
    }

    deleteItem = (id) => {
        const _arr = this.props.tab === 1 ? [...this.state.arr1] : [...this.state.arr2];
        const newArr = _arr.filter(item => item.id !== id);
        this.setState({ [this.props.tab === 1 ? 'arr1' : 'arr2']: newArr });
        this.props.setArr(newArr); // 向父组件传递数据
    }

    renderArr1 = () => {
        return this.state.arr1.map((item, index) => (
            <div key={item.id}>
                <span>{item.name}</span>----
                <button type="button" onClick={() => this.deleteItem(item.id)}>delete</button>
            </div>
        ));
    }

    renderArr2 = () => {
        return this.state.arr2.map((item) => (
            <div key={item.id}>
                <span>{item.name}</span>---
                <button type="button" onClick={() => this.deleteItem(item.id)}>delete</button>
            </div>
        ));
    }

    renderContent = () => {
        return this.props.tab === 1 ? this.renderArr1() : this.renderArr2();
    }

    render() {
        return(
            <div >
                <p>child</p>
                <div>{this.renderContent()}</div>
            </div>
        )
    }
}

export default Child;