Destructuring 解构赋值
props是一个对象,可以通过解构赋值减少代码的重复书写
props = {name: 'Arto Hellas',age: 35,}
在组件内解构
const Hello = (props) => {const { name, age } = props
在参数内解构
//import React from 'react'const Hello = ({ name, age, ...props }) => {console.log(props.gender)const bornYear = () => new Date().getFullYear() - agereturn (<><p>Hello {name}, you are {age} years old</p><p>So you were probably born in {bornYear()}</p></>)}const App = () => {const name = 'Peter'const age = 10return (<><h1>Greetings</h1><Hello name="Maya" age={26 + 10} gender='female' /><Hello name={name} age={age} /></>)}
Page re-rendering 页面重渲染
在App.js里显示一个数值,让它递增,当counter变化时,react不会自动刷新页面,需要手动刷新
const App = (props) => {const { counter } = propsreturn (<div>{counter}</div>)}
let counter = 1const refresh = () => {ReactDOM.render(<App counter={counter} />,document.getElementById('root'));}setInterval(() => {refresh() // 调用render手动刷新counter += 1}, 1000)
重复调用 ReactDOM.render-方法并不是重新渲染组件的推荐方法。 接下来,我们将介绍一种更好的,实现相同效果的方法。
Stateful component 有状态组件
我们通过 React 的 state hook 向应用的App 组件中添加状态。
每次 setCounter 修改状态时,它都会导致组件重新渲染。
import React, { useState } from 'react'const App = (props) => {const [counter, setCounter] = useState(0)setTimeout(() => setCounter(counter + 1),1000)return (<div>{counter}</div>)}
Event handling 事件处理
让点击按钮时counter加1
import React, { useState } from "react"const App = () => {const [counter, setCounter] = useState(0)const handleClick = () => {setCounter(counter + 1)}return (<div><div>{counter}</div><button onClick={handleClick}>plus</button></div>)}
事件处理函数也可以在 onClick 属性的值中直接定义:
<button onClick={() => setCounter(counter + 1)}>plus</button>
事件处理程序应该是一个函数 或一个函数引用
如果把onClick属性改成下面这样变成一个函数调用,当页面第一次渲染时,会调用setCounter(counter + 1),setCounter会导致页面再次渲染,形成死循环,最后页面崩溃
<button onClick={setCounter(counter + 1)}>plus</button>
通常在 JSX-模板 中定义事件处理程序并不是一个好的实践。
但这里没问题,因为我们的事件处理程序非常简单。
但无论如何,让我们将事件处理程序分离成单独的函数:
const App = () => {const [counter, setCounter] = useState(0)const increaseByOne = () => setCounter(counter + 1)const setToZero = () => setCounter(0)return (<div><div>{counter}</div><button onClick={increaseByOne}>plus</button><button onClick={setToZero}>zero</button></div>)}
Passing state to child components 将状态传递给子组件
在 React 中的一个最佳实践是将 状态提升 ,提升到组件层次结构中足够高的位置,文档中是这么说的:
Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor. 通常,几个组件需要反映相同的变化数据。 我们建议将共享状态提升到它们最接近的共同祖先。
让我们将counter和button拆分成组件,并将状态通过props传给这些子组件
const Display = (props) => {return (<div>{props.counter}</div>)}const Button = (props) => {return (<button onClick={props.handleClick}>{props.text}</button>)}const App = () => {const [counter, setCounter] = useState(0)const increaseByOne = () => setCounter(counter + 1)const decreaseByOne = () => setCounter(counter - 1)const setToZero = () => setCounter(0)return (<div><Display counter={counter} /><Button text={'plus'} handleClick={increaseByOne} /><Button text={'Zero'} handleClick={setToZero} /><Button text={'minus'} handleClick={decreaseByOne} /></div>)}
调用一个改变状态的函数会导致组件的重新渲染。
每次渲染,子组件的props就能获取到counter的最新值
Refactoring the components 重构组件
使用解构赋值和箭头函数特性重构子组件
const Display = ({ counter }) => <div>{counter}</div>const Button = ({ handleClick, text }) => (<button onClick={handleClick}>{text}</button>)
