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

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

以结果为导向,写给刚学完前端三剑客和想要了解 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.png


指令式 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.png



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


目录
相关文章
|
1月前
|
前端开发
react-router中的render、children、component
react-router中的render、children、component
68 1
|
23天前
|
前端开发 索引
解决React报错Encountered two children with the same key
解决React报错Encountered two children with the same key
|
1月前
|
前端开发 开发者
React 组件的 children 数据使用
React 组件的 children 数据使用
52 0
|
1月前
|
前端开发 JavaScript
React中通过children prop或者React.memo来优化子组件渲染【react性能优化】
React中通过children prop或者React.memo来优化子组件渲染【react性能优化】
53 0
|
10月前
|
前端开发
前端项目实战玖拾壹react-admin+material ui-踩坑-List的用法之children用法之SimpleList
前端项目实战玖拾壹react-admin+material ui-踩坑-List的用法之children用法之SimpleList
45 0
|
10月前
|
前端开发
前端项目实战玖拾react-admin+material ui-踩坑-List的用法之children用法之WithListContext
前端项目实战玖拾react-admin+material ui-踩坑-List的用法之children用法之WithListContext
37 0
|
10月前
|
前端开发
react children初步理解
react children初步理解
28 0
|
10月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-React keep alive原理之2
前端学习笔记202305学习笔记第二十九天-React keep alive原理之2
46 0
|
10月前
|
前端开发
前端学习笔记202306学习笔记第四十八天-react-admin marmelab之8
前端学习笔记202306学习笔记第四十八天-react-admin marmelab之7
32 0
|
1月前
|
前端开发 JavaScript
前端知识笔记(二十六)———React如何像Vue一样将css和js写在同一文件
前端知识笔记(二十六)———React如何像Vue一样将css和js写在同一文件
38 1