【问题标题】:how to pass props to multi-level components in react?如何在反应中将道具传递给多级组件?
【发布时间】:2021-08-09 02:21:07
【问题描述】:

您好我最近在做react,这里有个问题:那么如果我们想把props传递给多层次的组件,如何高效呢??

假设我有三个组件,Parent、Child、ChildOfChild。我想将道具从 Parent 传递给 ChildOfChild

我所做的是在 Child 和 ChildOfChild 中使用 componentWillReceiveProps

像这样: 家长:

import React, {Component} from "react";
// @ts-ignore
import Child from "./Child";


class Parent extends Component<any, any> {

    constructor(props) {
        super(props);
    }
    render() {

        return (
            <Child filters={this.state.filters} />

        );
    }
}
export default () => {

    return (<Parent/>)
}

孩子:


import React, {Component} from "react";
import ChildOfChild from "./ChildOfChild";

class Child extends Component<any, any> {
    constructor(props) {
        super(props);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.filters !== this.props.filters) {
            this.setState({filters: nextProps.filters});
        }
    }


    public render() {
        return <ChildOfChild
            filters = {this.state.filters}
            uri = {this.state.uri}
            label = {this.state.label} />
    }
}

export default Child

和 ChildOfChild:

import React from "react";
import {Component} from "react";

import * as _ from 'lodash';

import {makeStyles, createStyles} from '@material-ui/core/styles';
import {BackstageTheme} from '@backstage/theme'


const useStyles = makeStyles<BackstageTheme>(() =>
    createStyles({
        someStyle: {
            position: 'relative',
        }
    }),
);

interface Props {
    filters?: any,
    label?: string,
    uri?: string
}

class ChildOfChild extends Component<any, any> {

    constructor(props) {
        super(props);

    }


    componentWillReceiveProps(nextProps) {
        if (nextProps.filters !== this.props.filters) {
            this.fetchCountData(nextProps.filters);
        }

    }

    public componentDidMount() {

        this.fetchCountData(null);
    }

    public fetchCountData(filters) {
        if (filters != null && Object.keys(filters).length > 0) {
            // get data from api

        }
    }


    public render() {
        const popOverText = this.props.label;  // used somewhere
        const classes = this.props.classes;

        return (
            <p className={classes.someStyle}>
            {title}
            </p>
                
        );
    }
}

export default (props:Props) => {
    const classes = useStyles();
    return (
        <ChildOfChild classes={classes} {...props}/>
    )
}

我也尝试过“componentDidUpdate”,用法非常相似,但正如这里提到的:https://stackoverflow.com/a/51313510/11650363 它们是不同的。

所以我只想问我的解决方案如何?有什么缺点吗?? 将道具传递给多层的任何其他好的解决方案?

【问题讨论】:

  • 出于所有意图和目的,componentWillReceiveProps 已被弃用 (reactjs.org/docs/…)。只需将 props 传递给 child 的 child,不需要存储在中间组件的本地 state 中,实际上将传递的 props 存储到 state 中是 React 中的一种反模式。
  • @DrewReese 让你详细说明一下,如何传递道具而不将其存储在中间组件中,您的意思是删除中间组件???

标签: javascript reactjs react-native


【解决方案1】:

在本地组件状态中存储传递的 props 是 React 中的反模式,您应该将它们传递给子组件。出于所有意图和目的,componentWillReceiveProps 已被弃用,不应使用。为此,您应该实现 componentDidUpdate 生命周期方法并检查以前的 props/state 到当前 state/props 值,以发出任何副作用。

父母

class Parent extends Component<any, any> {
  state = {
    filters: [],
  }

  render() {
    return (
      <Child filters={this.state.filters} />
    );
  }
}

export default Parent

孩子

class Child extends Component<any, any> {
  constructor(props) {
    super(props);
    this.state = { ..... }
  }

  public render() {
    return (
      <ChildOfChild
        filters={this.props.filters} // <-- pass from props
        uri={this.state.uri}
        label={this.state.label}
      />
    );
  }
}

export default Child;

孩子的孩子

class ChildOfChild extends Component<any, any> {
  constructor(props) {
    super(props);
    ....
  }

  public componentDidMount() {
    this.fetchCountData(this.props.filters);
  }

  public componentDidUpdate(prevProps) {
    if (propProps.filters !== this.props.filters) { // <-- check if props updated
      this.fetchCountData(this.props.filters);
    }
  }

  public fetchCountData(filters) {
    if (filters != null && Object.keys(filters).length > 0) {
      // get data from api
    }
  }  

  public render() {
    const popOverText = this.props.label;
    const classes = this.props.classes;

    return (
      <p className={classes.someStyle}>
        {title}
      </p>      
    );
  }
}

【讨论】:

  • 很好的解决方案!我很困惑为什么在 Child 中不需要componentDidUpdate?我记得改变 props 不会强制组件重新渲染,对吧?
  • @HongliBu React 组件在其 state 和/或 props 更新时或在祖先组件重新渲染时重新渲染(即它将重新渲染其子树)。
【解决方案2】:

我建议你使用React Context(如果你熟悉 React 中的functional component)。 React Context 是 React 的一个库,用于控制应用中的全局状态。 states 可以是变量或函数。

您还可以使用其他全局状态管理,例如 React Redux(您不必在应用中使用 functional component)。

想象一下,如果您有一个具有这种层次结构的应用程序。

例如,如果想在Table Cell组件中访问App组件的状态,如果您手动将props从父组件传递到子组件,那将消耗您的精力和时间。

使用React ContextReact Redux,只需几行代码即可完成。

注:图片来源https://64.media.tumblr.com/bcfb43ecedb69f2ee8c0cae2b758ab35/tumblr_inline_ofcxnvTThG1rgj0aw_500.png

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 2018-07-21
    相关资源
    最近更新 更多