欢迎大家收看姊妹篇
苍天祝我:利用prop来理解vue的v-slot2 赞同 · 0 评论文章正在上传…重新上传取消
现在有这样一个组件,是用来切换一个<h1>
的显示与隐藏
// Toggle.js
import React, { useState } from "react";
export const Toggle = props => {
const [on, setOn] = useState(false);
const toggle = () => setOn(prev => !prev);
return (
<div>
{on && <h1>{props.children}</h1>}
<button onClick={toggle}>Show/Hide</button>
</div>
);
};
// App.js
<div>
<Toggle>
Hello World
</Toggle>
</div>
很简单对吧,可是这样就不能重用了,只能切换显示这个<h1>
,而且也只能点击这个button
来显示隐藏。
那如果能把on和toggle这两个API传到父组件就好了,子组件在里面用。子组件提供食材,父组件随便怎么玩。那么render prop应运而生。
首先得知道函数组件,除了通过jsx
还可以通过直接调用的方式来渲染。
function Render = ({on, toggle}) => {
return (
<div>Hello World</div>
)
}
// 1. 函数调用
Render({ on, toggle }) // props通过对象来传
// 2. jsx方式
<Render on={on} toggle={toggle} />
然后我们稍微改造一下代码
// ToggleRenderProps.js
import React, { useState } from "react";
export const ToggleRenderProps = props => {
const [on, setOn] = useState(false);
const toggle = () => setOn(prev => !prev);
const {Render} = props
return (
<div>
{Render({
on,
toggle
})}
<Render on={on} toggle={toggle}/>
</div>
);
};
// App.js
const Child = ({ on, toggle }) => (
<>
{on && <nav>Nav</nav>}
<div onClick={toggle}>click me</div>
</>
)
<div>
<Toggle
Render={Child}
/>;
</div>
其实就是Render
传了一个函数组件,然后子组件拿到这个函数组件,渲染这个函数组件,渲染的就是Child里return的jsx
。这就是为什么这种模式叫render props
,通过一个名为render
的prop
传一个函数给子组件,叫子组件来渲染这个函数,至于叫不叫render
那随便。而Child这个组件里on
和toggle
是哪里来的,就可以理解为子组件给的食材,我利用这个食材想生成什么jsx
就生成什么jsx
。
再改造一下
这样写起来还是有点不爽,在prop里传一个函数,能不能更直观一点呢,可以利用react自带的props.children
属性。上面的代码我们还得显示地传这个props.xxx,不过react自带了一个props.children。
之前是props.render=一个函数组件
,现在改造成props.children=一个函数组件
// ToggleRPC.js
import React, { useState } from "react";
export const ToggleRPC = props => {
const [on, setOn] = useState(false);
const toggle = () => setOn(prev => !prev);
const { children } = props;
return children({
on,
toggle
});
};
// App.js
export default function App() {
return (
<div className="App">
<ToggleRPC>
{({on, toggle})=>(
<div>
{on &&
<h1>Show Me</h1>}
<button onClick={toggle}>Show / Hide</button>
</div>
)}
</ToggleRPC>
</div>
);
}
可以看到只是从props.render=一个函数组件
变成了props.children=一个函数组件
,代码就清爽了许多