React開發中提高幸福度的一些小技巧

又一篇來自平常開發的彙總:各位客官請對號入席,店小二逐一上菜。
第一道菜:回鍋肉

react數組循環,基本都會設置一個惟一的key,表格的對象數組循環通常沒什麼問題,數據基本都會有一個id。那有種狀況就比較坑了,出如今表單形式的頁面結構中,對某個數組進行增刪改操做,通常對於非對象數組而言,沒有id,可能不少人會偷懶,循環的時候,直接設置數組的下標index做爲key,當出現增刪改時候,就會出現數據對不上或者從新渲染組件的問題等。解決方案有不少種,例如把字符串數組等重組對象數組,每一個元素設置一個惟一id等。另外有個方式:推薦使用shortid生成惟一key的數組,和數據數組一塊兒使用,省去提交數據時再重組數組。html

import React from 'react';
import shortid from 'shortid';

class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: ['a', 'b', 'c']
        }
        this.dataKeys = this.state.data.map(v => shortid.generate());
    }
    
    deleteOne = index => { // 刪除操做
        const { data } = this.state;
        this.setState({ data: data.filter((v, i) => i !== index) });
        this.dataKyes.splice(index, 1);
    }
    
    render() {
        return (
            <ul>
               {
                   data.map((v, i) => 
                    <li 
                        onClick={i => this.deleteOne(i)}  
                        key={this.dataKeys[i]}
                    >
                        {v}
                    </li>
                    )
               } 
            </ul>
        )
    }
}
// 稍微抽取,能夠封裝一個通用的組件
第二道菜:番茄炒蛋

經過判斷值是否存在來控制元素是否顯示,通常三目運算能夠達到此效果,最簡單的仍是用短路的寫法:react

// 不錯
const flag = 'something';
flag && <div></div>

// 很好
// 注意通常可能上面寫法多一些,但當flag爲0 的時頁面上會顯示0,用!!將其轉爲boolean避免坑,
// 代碼也更規範
const flag = 'something';
!!flag && <div></div>
第三道菜:酸辣土豆絲

使用組件,傳遞props:git

const { data, type, something } = this.state;
<Demo 
    data={data}
    type={type}
    something={something}
/>

也許另一種傳遞方式更簡潔:github

const { data, type, something } = this.state;
<Demo 
    {...{ data, id, something }}
/>
第四道菜:清炒時蔬

組件的props有時候會定義不少,可是調用組件傳遞props的時候又想一個個傳,不想一次性傳遞一個option對象,經過擴展運算符和解構賦值能夠簡化此操做:數組

const Demo = ({ prop1, prop2, prop3, ...restProps }) => (
    <div>
        xxxx
        { restProps.something }
    </div>
)
// 父組件使用Demo
<Demo
    prop1={xxx}
    prop2={xxx}
    something={xxx}
/>
第五道菜:小吃-餈粑

通常改變state值的一種方式:性能優化

const { data } = this.state;
this.setState({ data: {...data, key: 1 } });

另一種能夠經過callback的方式改變state的值antd

this.setState(({ data }) => ({ data: {...data, key: 1 } }));

還能夠:app

this.setState((state, props) => {
    return { counter: state.counter + props.step };
});
第六道菜:水煮肉片

React 性能優化有不少種方式,那常見的一種就是在生命週期函數shouldComponentUpdate裏面判斷某些值或屬性來控制組件是否從新再次渲染。ide

判斷通常的字符串,數字或者基礎的對象,數組都仍是比較好處理,那嵌套的對象或者數組就比較麻煩了,對於這種,能夠轉成字符串處理,但屬性值的位置不一樣時,那就無效了。函數

推薦使用lodash(或者其餘的相似庫)的isEqual對嵌套數組或對象進行判斷(相比其餘方式更簡單些)

shouldComponentUpdate(nextProps, nextState) {
    if (_.isEqual(nextState.columns, this.state.columns)) return false;
    return true;
}
第七道菜:幹鍋兔

建立彈層的三種方式:

  1. 普通組件經過state和樣式控制,在當前組件中顯示彈層-每次引入組件而且render裏面控制顯示,掛載節點在某組件裏面
// 彈層 
const Dialog = () => <div>彈層</div>
// 某組件
render() {
    return (
        this.state.showDialog && <Dialog />
    )
}

2.經過Portals建立通道,在根節點外部掛載組件-但仍是須要每次引入而且在render裏面調用

// 彈層 
class Dialog extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }
  componentDidMount() {
    modalRoot.appendChild(this.el);
  }
  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children || <div>xxxx</div>,
      this.el,
    );
  }
}
// 某組件
render() {
    return (
        this.state.showDialog && <Dialog />
    )
}

3.推薦使用ReactDom.render建立彈層-掛載根節點外層,使用也更方便

// demo
let dialog;
class Dialog {
    show(children) {    // 顯示
        this.div = document.createElement('div');
        document.body.appendChild(this.div);

        ReactDom.render(children || <div>xxxx</div>, this.div);
    }
    destroy() {     // 銷燬
        ReactDom.unmountComponentAtNode(this.div);
        this.div.parentNode.removeChild(this.div);
    }
}
export default {
    show: function(children) {
        dialog = new Dialog();
        dialog.show(children);
    },
    hide: xxxxx
};
// 某組件
import Dialog from 'xxx';
alert = () => {
    Dialog.show(xxxx);
}
render() {
    return (
        <button onClick={this.alert}>點擊彈層</button>
    )
}
第八道菜:火燒肉

render props是如今很流行的一種渲染方式,經過回調函數,渲染子組件,參數可爲父組件的任意屬性值(官網也有相應的介紹)新版的contextApi也採用了這個模式。

不少種場景使用此方式的作法:

// 權限控制組件,只須要封裝一次connect,
// 經過render props向子組件傳遞權限
class AuthWidget extends Component {
    render() {
        return this.props.children(this.props.auth);
    }
}

const mapStateToProps = state => {
    const { auth } = state;
    return { auth: state.auth };
};
export default connect(mapStateToProps)(AuthWidget);

// 其餘組件使用
<AuthWidget
    children={auth => auth.edit && <a>編輯</a>}
/>

// 使用antd的form時
const Test = ({ form, children }) => {
    return children(form);
};
const FormTest = Form.create()(Test);

class Demo extends Component {
    render() {
        return (
            <div>
                xxxxx
                <FormTest>
                    { form => {
                        this.form = form;
                        return (
                            <Form>
                                <Form.Item>
                                    {getFieldDecorator('field', xxx)(
                                        <Input placeholder="請輸入連接地址" />
                                    )}
                                </Form.Item>
                            </Form>
                        )
                    }}
                </FormTest>
            </div>
        )
    }
}
第九道菜:粉絲白菜蝦仁湯

子組件改變父組件的state方式有不少種,能夠在父組件設置一個通用函數,相似:setParentState,經過子組件回調處理時,就能夠更方便的統一處理:

// 父組件
state = {
    data: {}
}
setParentState = obj => {
    this.setState(obj);
}
// 子組件
onClick = () => {
    this.props.setParentState({ data: xxx });
}
第十道菜:麻婆豆腐

永遠不要直接設置state的值:this.state.data = { a: 1 }。這個會致使幾個問題:
1:組件不會從新渲染 2:shouldComponentUpdate(nextProps, nextState) 函數裏面 this.state的值是已經改變了,和nextState的值相同。

舉個栗子:

// wrong
const { data } = this.state;
data.a = 1;     // 等價於this.state.data.a = 1;
this.setState({ data }); // shouldComponentUpdate裏面觀察到 this.state 和nextState的值是相同的
// 此時函數裏面性能相關的優化是無效的

// correct  須要用到當前state值的寫法
this.setState(state => ({ data: {...state.data, a: 1} }))
各位客官,菜已上齊,請慢用

react相關討論,請加Q羣:743490497

相關文章
相關標籤/搜索