react萌新的读书笔记(一) 书的地址 子传父 插槽 Fragment 上下文(Context) react-hooks 决定自己的高度的是你的态度,而不是你的才能 记得我们是终身初学者和学习者


链接: https://pan.baidu.com/s/1YC0qS2QFJO3yQ-kFt27lBQ 提取码: h2km

子传父

通过方法

父组件

export default class TheOne extends Component {
    constructor(props) {
        super(props);
    }

    setNum(e) {
        console.log(e);
    }
    render() {
        return (<>
            <MarginTop setNum={this.setNum}/>
        </>)
    }
}

子组件

class MarginTop extends Component {
    constructor(props) {
        super(props);
    }
    onChangesOne =()=>{
        this.props.setNum('cccc')
    };
    render() {
        return <>
            <button onClick={this.onChangesOne}>Click</button>
        </>
    }
}

prop-types 父传子属性限制

    static propTypes = {
        age: PropType.number
    }

defaultProps 设置默认值

class First extends Component {
    constructor(props) {
        super(props);
    }

    static defaultProps = {
        num: 1,
        a: 2
    }

    render() {
        let {num,a}=this.props
        return <><h1>First--{num+a}</h1></>
    }
}

箭头函数的方式

 <MyButton disabled={false} test={'xxxx'}/>

const MyButton = ({disabled, test}) => {
    return <button disabled={disabled}>{test}</button>
}   

模拟父传子的请求

父
export default class TestTwo extends Component {

    constructor(props) {
            super(props);
            this.state = {
                arr:[]
            }
        }
    fetchDate(){
            return new Promise(res=>setTimeout(()=>{
                res(['a','b','c'])
            },2000))
        }
        componentDidMount() {
            this.fetchDate().then(res=>{
                this.setState({
                    arr:res
                })
            })

        }
     render() {
            let {arr} = this.state
            return (<>
                <MyButton disabled={false} test={arr}/>
            </>)
        }
}

const MyButton = ({test}) => {
    return (<>
        <ul>
            {test.map((val,i)=>{
                return <li key={i}>{val}</li>
            })}
        </ul>
    </>)
}

插槽

 <TestTwo>
                <TestTen/>
 </TestTwo>

export default class TestTwo extends Component{
    constructor(props) {
        super(props);
    }
    componentDidMount() {
        console.log(this.props.children);
    }

    render(){
        return (<div>
            two
            {this.props.children} // 会把TestTen 放在这里
        </div>)
    }
}

如果想调整顺序

 <TestTwo>
                <TestTen/>
                <TestConfig />
</TestTwo>

========
     <div>
            {this.props.children[0]}
            two
            {this.props.children[1]}
        </div>

另一种方式的插槽

父
 <TestTwo>
                <TestTwo.First/>
 </TestTwo>
子
class First extends Component{
    render(){
        return <><h1>First</h1></>
    }
}
export default class TestTwo extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        let {first, second} = this.state
        return (<>
          	Two
            {this.props.children}
        </>)
    }
}

TestTwo.First=First;

Fragment

对子列表分组,无需向DOM 添加节点

<Fragment>
            {this.props.children[0]}
            two
            {this.props.children[1]}
 </Fragment>)

短语法
<>
xxxx
</>    

key 是唯一可以传递给 Fragment 的属性

上下文(Context)

// context.js
import React from 'react'

export default React.createContext({})

//theThree.js
import React, {Component, createContext} from 'react'
import TestTwo from "./TestTwo";
import ThemeContext from './context'


export default class TestThree extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return <>
            <h1>TestThree</h1>
            <ThemeContext.Provider value={{
                foo:'bar',
                baz:'blah'
            }}>
                <TestTwo/>
            </ThemeContext.Provider>
        </>
    }
}

// TestTwo
import React, {Component} from 'react'
import ThemeContext from './context'

export default class TestTwo extends Component {
    constructor(props) {
        super(props);
    }
    static contextType=ThemeContext;
    componentDidMount() {
        console.log(this.context);
    }


    render() {
        return <>
            <h1>TestTwo</h1>
        </>
    }
}
// 箭头函数版
const Four=(props)=>{
    return (<ThemeContext.Consumer className="Consumer">
        {({foo,baz})=>{
            return (<h1>{foo}---{baz}</h1>)
        }}
    </ThemeContext.Consumer>)
}
// hooks 版
const Four = (props) => {
    const count=useContext(ThemeContext)
    useEffect(() => {
        console.log(count);// 拿到值了
    });
    return (<>
        xxx
    </>)
}

如果跟我一样出现报错了

createContext调用移动到单独的文件/模块可以解决我们的问题

react-hooks

useState

双向绑定

const Four = (props) => {
    const [age, setAge] = useState('xxx');
    return (<>
        <input type="text" value={age}
               onChange={e => setAge(e.target.value)}
        />
        {age}
    </>)
}

把父的状态和修改都传给子修改

const Four = (props) => {
    const age=useState(10)
    return (<>
        xxx
        <ThemeContext.Provider value={age}>
            {age[0]}
            <TestTwo />
        </ThemeContext.Provider>
    </>)
}
子
export default class TestTwo extends Component {
    constructor(props) {
        super(props);
    }
    static contextType=ThemeContext;
    componentDidMount() {
    }


    render() {
        const [value,setValue]=this.context;
        return <>
            <h1>{value}</h1>
            <button onClick={()=>setValue(12)}>修改</button>
        </>
    }
}
如果是箭头函数
const Fill=props=>{
    const [status,setStatus]=useContext(ThemeContext)
    return (<>
        {status}
        <button onClick={()=>setStatus(111)}>修改</button>
    </>)
}

useEffect

清楚订阅

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // 清除订阅
    subscription.unsubscribe();
  };
});
useEffect(
  () => {
    console.log(1)
  },
  [props.source],
);

只有当props.source 改变后才会重新创建订阅