一. connect
- connect是一个科里化的函数,接受两个参数:mapStateToProps数据绑定、mapDispatchToProps事件绑定
connect(mapStateToProps,mapDispatchToProps)(component)
- mapStateToProps
添加redux时,自动初始化, 用来建立和store的state之间的关系。(如果写了第二个参数ownProps,那么当prop发生变化的时候,mapStateToProps也会被调用。)
function mapStateToPros(state,ownProps){
return {
}
}
- mapDispatchToProps
建立组件和store.dispatch之间的联系,接受dispatch,返回props中的回调方法
二. 生命周期相关
- componentWillReceiveProps
(1)用法:componentWillReceiveProps在初始化render时候不会执行,会在接受到新的prop时候触发
(2)写法:比较两个prop,在自组件中对state进行改变然后重新渲染组件或者是触发子组件内的某些方法;同时,可以不用把所有的请求放在父组件中。可以子组件接受prop,请求只在子组件渲染时才会发出,减轻请求负担。
componentWillReceiveProps(nextProps) {//componentWillReceiveProps方法中第一个参数代表即将传入的新的Props
if (this.props.show !== nextProps.show){
if (nextProps.show){
this.getData();
}
}
}
(3)问题
如果if (nextProps.show)内改变父组件的prop,很有可能会死循环
- shouldComponentUpdate
见下面PureComponent
(1)为什么有这个函数?
减少组件不必要的渲染,调用setState,即使是更新的state没有地方使用或者和渲染无关,依然会重新渲染;父组件的重新渲染,造成子组件可能无用的重新渲染
(2)
三. 组件类别
- 受控组件和非受控组件
import React,{Component} from 'react';
class ControlComponent extends Component {
constructor(props){
super(props)
this.state = {
controlValue: "index"
}
this.handleChange=this.handleChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
}
handleChange(e){
console.log(e.target.value);
this.setState({
controlValue: e.target.value
})
}
handleSubmit(){
console.log(this.refs.textInput.value)
}
render(){
return(
<div>
<input type={"text"} value={this.state.controlValue} onChange={this.handleChange}/>{this.state.controlValue} //受控组件
<input type={"text"} ref={"textInput"}/> //非受控组件
<button onClick={this.handleSubmit}></button>
</div>
)
}
}
export default ControlComponent
主要通过<input/>、<textarea/>、<select/>这类表单元素。
受控组件:动态设置初始化,需要显示某个值
非受控组件:无动态显示初始化信息的必要,通过this.ref.xxx.value获取值
使用:偏向于使用受控组件
ref:React的ref属性,代表对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例;
ReactDOM.render()渲染组件时返回的是组件实例;而渲染dom元素时,返回是具体的dom节点。
refs: 我们通过refs方法访问DOM节点或者React组件实例
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
ref 会在 componentDidMount 或 componentDidUpdate 生命周期钩子触发前更新。- 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
<CustomTextInput ref={this.textInput} />
class CustomTextInput extends React.Component {
// ...生命为class有效
}
- 不能在函数组件上使用 ref 属性,因为他们没有实例。
import React,{Component} from 'react';
function TextInput(prop){
return (
<div>
<input ref={prop.inputRef}/>
</div>
)
}
class ControlComponent extends Component {
constructor(props){
super(props)
this.inputElement = null;
this.setInputElement = element => {
this.inputElement = element;
}
this.focusInputElement = () => {
if(this.inputElement) this.inputElement.focus()
}
}
componentDidMount(){
this.focusInputElement();
}
render(){
return(
<div>
<TextInput inputRef={this.setInputElement}/>
// 在 ControlComponent 中的 this.inputElement 会被设置为与 TextInput 中的 input 元素相对应的 DOM 节点
</div>
)
}
}
export default ControlComponent
建议用回调函数或 createRef API 的方式代替。
- 高阶组件
高阶组件输入一个组件,返回新组件
function withSubscription(WrappedComponent,selectData){
return class extends React.Component {
constructor(props){
super(props)
}
// 通用函数
render() {
return <WrappedComponent {...this.props}/>
}
}
}
WrappedComponent.prototype不能修改组件原型
- Hoc
(1) useState
useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。
const [count,useCount] = useState(0)
(2)useEffect
和class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途
作用:希望在组件加载和更新时执行同样的操作,需要 componentDidMount、componentDidUpdate重复代码;对比class的用法,通常需要在 componentDidMount 中设置订阅,并在 componentWillUnmount 中清除它。
hooks如何执行清除?
hooks中useEffect中return的函数会在清除时执行,在组件卸载时执行, 会在执行当前 effect 之前对上一个 effect 进行清除
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
- Hook 不能在 class 组件中使用
- 只能在函数最外层调用 Hook
- PureComponent
(1)用法
和React.Component用法几乎完全相同;
(2)原理
主要通过prop和state的浅比较(shallowEqual)实现React.Component的shouldComponentUpdate(),当前浅比较出现的问题就是深层次的数据结构发生改变,但是仍然不重新渲染,如果在React.Component中应该要这么写
shouldComponentUpdate(nextProps,nextState){
return (
!shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState)
)
}
(3)shallowEqual 源码
不会递归的去深层比较,通过Object.keys()获取key,key和value都是简单数据结构,否则为复杂;一旦检测出key或者value不一致,则直接返回false;全部相同则为true
为什么用浅比较?
因为都是用深比较,过于浪费性能,不一定比不进行处理来的快
四. state
- state基础内容和写法
https://blog.csdn.net/qq_33281069/article/details/83113909
reducer(previousState,action)=>newState