Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 组件默认值及 TS 配置 #59

Open
jtwang7 opened this issue Dec 11, 2022 · 0 comments
Open

React 组件默认值及 TS 配置 #59

jtwang7 opened this issue Dec 11, 2022 · 0 comments

Comments

@jtwang7
Copy link
Owner

jtwang7 commented Dec 11, 2022

React 组件默认值及 TS 配置

React 组件默认值配置

React 组件字段 defaultProps 可以为 React 组件添加默认 props。这一般用于 props 未赋值,但又不能为 null 的情况。
无论是 class component 还是 function component 都存在这个属性字段。

🌈 Class Component

type GreetProps = typeof Greet.defaultProps & {
  age: number;
};

class Greet extends React.Component<GreetProps> {
  static defaultProps = {
    age: 21,
  };
  /*...*/
}

// static 属性值可以被提到 class 外部,因此也可以写为:
Greet.defaultProps = { age:21 };

// Type-checks! No type assertions needed!
let el = <Greet age={3} />;

🌈 Function Component

// using typeof as a shortcut; note that it hoists!
// you can also declare the type of DefaultProps if you choose
// e.g. https://github.com/typescript-cheatsheets/react/issues/415#issuecomment-841223219
type GreetProps = { age: number } & typeof defaultProps;

const defaultProps = {
  age: 21,
};

const Greet = (props: GreetProps) => {
  // etc
};
Greet.defaultProps = defaultProps;

👋 goodBye defaultProps

根据 👉 这条推文defaultProps 最终将被弃用。目前的共识是使用对象默认值。

🌈 Class Component

type GreetProps = {
  age?: number;
};

class Greet extends React.Component<GreetProps> {
  render() {
    const { age = 21 } = this.props;
    /*...*/
  }
}

let el = <Greet age={3} />;

🌈 Function Component

type GreetProps = { age?: number };

const Greet = ({ age = 21 }: GreetProps) => // etc

深层 props 对象的默认赋值

对于简单的 props 对象,我们可以通过解构赋值。但对于深层嵌套对象而言,单层解构赋值会存在以下情况:

const {
  a = 4,
  b = {
    b1: 2,
    b2: {
      b2_1: true,
    }
  }
} = props;
// props -> 
// {
//   a: 5,
//   b: {
//    b1: 9,
//   }
// }

// b.b2 === undefined

b 默认属性赋值如上,但在传参过程中传递了 b: {b1: 5},则上面 b 属性就会被判别为已赋值,默认赋值的完整对象被覆盖。因此当我们访问 b.b2 时返回 undefined

🌈 对于深层嵌套对象,我们可以编写函数递归执行默认赋值,但通常情况下,我们可以声明一个 defaultProps 常量,在需要默认值判别处调用 defaultProps 内部的属性字段即可。

const defaultProps = {
  a: 4,
  b: {
    b1: 2,
    b2: {
      b2_1: true,
    }
  }
}

// props.b.b2 ?? defaultProps.b.b2

🔥 lodash.defaultsDeep

使用方法:默认项在后,目标项在前。目标项中已存在的字段不会被覆盖,目标项中未定义(undefined)的字段,将从后续项中取值填补,若存在多个后续项,则依次寻找字段填补直至遇到第一个可用值为止。

const default = {
  cell: {
    width: 10,
    height: 10,
    color: "summer",
  },
  font: {
    size: 10,
    weight: "normal",
  },
  padding: [20, 20, 20, 20],
  needTopBar: false,
  needRightBar: false,
  needColorBar: true,
}
_.defaultsDeep(options, default)

👉 注意:不要将 React Component props 直接应用于 _.defaultsDeep() 函数,这将不起作用,原因未知。为 React props 赋予深层默认值的方法如下:

const p = useMemo(() => (_.cloneDeep(props)), [props]); // 深拷贝 props 对象
const target = useMemo(() => (_.defaultsDeep(p, { ... })), [p]); // 对副本进行默认赋值

👋 lodash.defaultsDeep 函数默认赋值存在的问题

lodash.defaultsDeep 会递归进行默认赋值,但当递归的元素为数组时,该函数会遍历数组内的各个元素。假如传参中嵌套数组的长度与默认对象嵌套数组长度不同,则结果是合并而非替换。

const a = {
  data: [1, 2, 3]
}
const b= {
  data: [5, 6, 7, 8, 9]
}
_.defaultsDeep(a, b)
// {data: [1, 2, 3, 8, 9]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant