一、渲染属性RenderProps
渲染属性是一种React组件之间使用一个值为函数的props共享代码的简单技术
简单来说,我在父组件中向子组件添加了一个函数,子组件通过函数的调用传入一个值或者模板,来调用父元素方法,或者将模板插入组件
使用案例
在常规的组件应用时有一个能够捕获鼠标位置的类组件**<catchLoca>他的状态只能他自己调用,而我想要真正应用的是一个能够让鼠标移动后让一个背景块跟随,这时候只能通过向<catchLocal>**组件中添加一个新的逻辑与标签,
可以根据滑块封装一个**<moveRect>组件,并把组件放在<catchLocal>中让他能够使用<catchLocal>组件的状态,但这样<catchLocal>**得复用性就大大降低,他不是一个仅仅计算位置的组件
为了提高复用性我们想要将****的位置状态暴露给外部,让外部根据他的状态来进行自己的自定义设置,这样这个组件在任何需要使用鼠标位置的地方都能使用了,这其实就是作用域插槽的思想
实现
组件想要让状态传给父元素可以采用调用父组件函数的方式来将状态传给父组件,父组件会根据这个方法来返回一个jsx模板
RenderProps
做鼠标位置的检测
import React, { Component } from "react";
export default class RenderProps extends Component {
constructor(defaultProps) {
super()
this.state = { //创建初始状态
x:0,
y:0
}
}
mousemove = ({clientX,clientY}) => { //刷新鼠标位置
this.setState({
x:clientX,
y:clientY
})
}
render() {
return (
<>
<div style={{height:"100vh"}} onMouseMove={this.mousemove}>
{this.props.children({...this.state})} //将更改的状态返回给外部
</div>
</>
)
}
}
RenderProps只是将状态传给了,外部给定的函数,至于函数要做什么,RenderProps并不考虑
子状态渲染组件
App
return (
<>
<div>
<p>这是父组件,我现在需要子组件内容</p>
<hr />
<RenderProps> //引入组件通过
{({x,y}) => (
<div>{`现在的位置${x},${y}`}</div> //外部组件来进行呢状态的处理逻辑
)}
</RenderProps>
</div>
</>
)
传入的函数一定不能操作state,可以进行其他方法的调用,但方法中也不能修改state
为什么不能传入一个操作父元素state的函数
react认为,在render函数中进行操作state的是一种危险的行为,很有可能造成死循环的情况,即使用shouldComponentUpdate来进行判断拦截,也是不合理的,所以会报错
正确的做法应该是我们将改变state的方法放在一个按钮这样的触发性dom中,这样在render的时候并不执行,而是在交互时更改state