2022 React 最速上手指南(十二)—— children prop & 指令式 React

这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

以结果为导向,写给刚学完前端三剑客和想要了解 React 框架的小伙伴,使得他们能快速上手(省略了历史以及一些不必要的介绍)。

children prop

You can think of a component with a children prop as having a “hole” that can be “filled in” by its parent components with arbitrary JSX.

我们将通过 React 的 children prop 像使用 HTML 开合标签一样使用 React 元素,把之前使用的文本 ”Search: “ 从上层传下来,不再使用 label prop:

const App = () => {
  ...

  return (
    <>
      <InputWithLabel
        id="search"
        value={searchTerm}
        onInputChange={handleSearch}
      >
        <strong>Search:</strong>
      </InputWithLabel>

      <hr />
      <List list={searchedStories} />
    </>
  );
};

const InputWithLabel = ({
  id,
  value,
  type = "text",
  onInputChange,
  children,
}) => (
  <>
    <label htmlFor={id}>{children}</label>
    &nbsp;&nbsp;
    <input id={id} type={type} value={value} onChange={onInputChange} />
  </>
);
复制代码

我们可以把字符串, HTML 元素 <strong> ,以及【组件】等任意 JSX 元素当作 React children 传递,有了这个特性,我们可以就像使用 HTML 元素一样交织使用 React 组件。

image-20220222130531652

指令式 React

从 JSX 到 hook,一直都是我们告诉 React 去渲染什么,而不是怎么去渲染,所以 React 天生是声明式的。

但并不是所有时候都能使用声明的方式,有些情况我们不免要通过指令式的方式去访问渲染好的 JSX 元素,比如我们需要调用 DOM API 的 focus() 方法给搜索框添加一个自动聚焦的功能。

  • 命令式写法,设定属性值:
const App = () => {
	...
  
  return (
    <>
      <InputWithLabel
        id="search"
        value={searchTerm}
        onInputChange={handleSearch}
        isFocused
      >
        <strong>Search:</strong>
      </InputWithLabel>

      <hr />
      <List list={searchedStories} />
    </>
  );
};

const InputWithLabel = ({
  id,
  value,
  type = "text",
  onInputChange,
  children,
  isFocused,
}) => (
  <>
    <label htmlFor={id}>{children}</label>
    &nbsp;&nbsp;
    <input
      id={id}
      type={type}
      value={value}
      onChange={onInputChange}
      autoFocus={isFocused}
    />
  </>
);
复制代码
  • 指令式写法,通过程序调用 DOM API:
const InputWithLabel = ({
  id,
  value,
  type = "text",
  onInputChange,
  children,
  isFocused,
}) => {
  const inputRef = React.useRef();	// 1
  React.useEffect(() => {  // 3
    if (isFocused && inputRef.current) {
      inputRef.current.focus();  // 4
    }
  }, [isFocused]);

  return (
    <>
      <label htmlFor={id}>{children}</label>
      &nbsp;&nbsp;
			{/* 2 */}
      <input
        ref={inputRef}
        id={id}
        type={type}
        value={value}
        onChange={onInputChange}
      />
    </>
  );
};
复制代码
  1. 首先,使用 useRef hook 创建一个 ref ,也就是一个引用对象。它在组件的整个生命周期中保持不变,向外暴露一个可变的 current 属性,并把初始化被传入的参数作为 current 属性值。
  2. 把 ref 对象通过 JSX 的 ref 标签传递给输入框之后,这个 DOM 节点就会被赋给 current 属性,也就是说 inputRef.current 现在已经指向了挂载在 DOM 上的输入框节点。
  3. 调用 useEffect hook,当组件渲染或是依赖数组改变时,使焦点落在输入框上。
  4. 最后,当设置了 isFocused 并且 current 属性存在时,通过 current 属性访问到输入框实现自动聚焦。

Essentially, useRef is like a “box” that can hold a mutable value in its .current property.

image-20220223001711768

也就是说我们通过 useRef hook 拿到了 DOM 节点并且调用了 DOM API,把原来的声明式转换为了指令式,更多 useRef 的用法可以查看官方文档

专栏

因为参加打卡活动是每日更新,所以可能比较短小,可以关注一下 React 入门专栏

在更新完后会整合为一整篇,感谢关注和点赞!

Guess you like

Origin juejin.im/post/7067741026353414152