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() - age
return (
<>
<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 = 10
return (
<>
<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 } = props
return (
<div>{counter}</div>
)
}
let counter = 1
const 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>
)