react 合并数组_React 常被忽视的细节。
一. 數組循環時的key值
為了幫 React 實現 數組的最優調和(reconciliation)時,我們需要為循環的組件加上 key,不然React 會提示 :
然后為了圖方便,很多人就會直接將 Array.map(item, index) 中的 index 當作 key 值:
const Arr = [{ name:'Larry'}, { name:'Lucy'} ];Arr.map((item, index)=>(<div key={index}>{item}</div> ))雖然React不報錯了,但是這樣是錯誤的 ?
必須保證 Arr 無論怎么變,從2個增加到5個或者n個,key都是唯一且不會變化。
二. React組件unmounted之后setState的報錯處理
我們常在 componentDidMount 里面(最好別在其他生命周期中執行ajax) 進行 ajax 請求,然后在回調函數中 通過 setState 來render視圖,這是無可厚非的。但是偶爾會報錯:
這是因為在組件卸載后執行了setState。
state = { name : 'Lucy' } let time; componentDidMount(){time = setTimeout(()=>{this.setState({ name:'Larry' })},5000) }這段代碼表示在組件加載完成后的5s后,執行 this.setState({ name:'Larry' }) ,但是如果在這5s內,你切換到其他組件或者頁面(不包含該組件),該組件不存在了,就會報上面的錯。
解決方法就是在 componentWillUnMount 中釋放掉計時器。
componentWillUnMount(){clearTimeout(time) }鑒于大家經常使用fetch,在 componentWillUnMount cancel掉fetch的then就行了。
三. 子組件屬性使用內嵌對象 或者 匿名函數
有些同學為了優化性能,構建組件時使用了shouldComponentUpdate 或者 PureComponent,就以為大功告成了,只要父級傳來的props不變,子組件就不會被二次render了,其實不然。。。
class Child extends React.PureComponent{render(){...} }class Parent extends React.PureComponent{render(){return(<Child onClick={ ()=>console.log(11) } style={{ color:'#ccc' }}/>)} }上面代碼中,onClick 和 style 是匿名函數和內嵌樣式,每次父組件執行render,都會重新為這兩個分配內存,子組件就會被重新渲染,兩次render后的內存地址不相同,shouldComponentUpdate 和 PureComponent 就起不了作用。
把父組件改為下面就行:
const style = { color:'#ccc' }class Parent extends React.PureComponent{onClick = () => {console.log(11)}render(){return(<Child onClick={ this.onClick } style={ style }/>)}}這樣,父組件執行 render 就不會再重新生成 onClick 和 style 對應的函數和值了。
四. fetch的HTTP狀態碼
fetch作為現在被廣泛使用的網絡訪問方式,promise的鏈式調用方法解決了困擾前端工程師很長一段時間的回調地獄。然而,這個特性有一點不足,就是無論 http 狀態碼返回 404 或者 500,鏈式中的then一樣會被調用,不會直接被catch捕獲。
所以我們需要在第一次then中就判斷 狀態碼是否 === 200 ?返回新的Promise : 拋出異常;
fetch(url).then((res)=>{if(res.status !== 200){throw new Error ('請求失敗')}res.json().then((res)=>{//繼續后面的操作}).catch(err=>{console.log(err)})}).catch(err=>{console.log(err)})五.在專用組件中渲染列表
這點在渲染大型數據集合時尤為重要。 React 在渲染大型數據集合時表現非常糟糕,因為協調器必須評估每個集合變化的集合所產生的組件。 因此,建議使用專門的組件來映射集合并渲染這個組件,且不再渲染其他組件:
bad:
class MyComponent extends Component {render() {const {todos, user} = this.props;return (<div>{user.name}<ul>{todos.map(todo => <TodoView todo={todo} key={todo.id} />)}</ul></div>)} }在上來的示例中,當 user.name 改變時,React 會不必要地協調所有的 TodoView 組件。盡管TodoView 組件不會重新渲染,但是協調的過程本身是非常昂貴的。
good:
class MyComponent extends Component {render() {const {todos, user} = this.props;return (<div>{user.name}<TodosView todos={todos} /></div>)} }class TodosView extends Component {render() {const {todos} = this.props;return <ul>{todos.map(todo => <TodoView todo={todo} key={todo.id} />)}</ul>)} }六. 子組件避免render
有些時候,我們在父組件中使用子組件,希望通過屬性傳遞,讓子組件自身控制顯示還是隱藏,可以通過 return null 來避免render。
const Child = ({ show }) => {if (!show) {return null;}return (<div>child component</div>);}class Parent extends React.Component{state = {show:true}toggle = () => {this.setState({show: !this.state.show})}render(){return(<div><Child show={this.state.show}/><Button onClick={this.toggle}>隱藏/顯示</Button></div>)} }七. setState是異步的
在一次的函數運行中,setState不會立即執行,而是會等函數執行完成后,對多次state的操作進行合并(相同的state屬性后者覆蓋前者,不用的屬性合并),然后進行一次setState。
class Demo extends React.Component{state = {number:1}add = () => {this.setState({number:this.state.number++})console.log(this.state.number)//輸出1,沒有變,說明setState是異步的,因為沒有立即執行//再執行一次this.setState({number:this.state.number++})console.log(this.state.number)//還是輸出1}print = () => console.log(this.state.number)}add();//執行add方法,調用了兩次setState print();//輸出2,說明只對number進行了一次++這樣設計的原因: 1.合并更新,減少Dom渲染,降低頁面性能。 2.即使每次執行setState都進行渲染,用戶也看不到中間效果,只能看見最終的state渲染的頁面未完待續。。。
總結
以上是生活随笔為你收集整理的react 合并数组_React 常被忽视的细节。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上网课的心得体会1000字_上网课心得体
- 下一篇: java主类与源代码名称_java 获取