使用react開發的經驗總結(持續更新)

1.頁面的跳轉攜帶參數的問題

我的頁面很多都會進行頁面的跳轉,而下一個頁面的信息都是跟上頁面相關聯的,及時我跳轉的頁面所需要的信息,在跳轉前的頁面都是存在的,所以我第一個想的方法就是在跳轉路由的時候,通過傳參的方式,進行數據的傳遞,所以我是用了location中的state來存儲我傳的數據.

const data=record;

? ? ? ? ? ? ? ? const path = {

? ? ? ? ? ? ? ? ? ? pathname:'/person/releaseDetial',

? ? ? ? ? ? ? ? ? ? state:{data},

這樣傳遞的數據,我直接在新的頁面通過this.props.history.location中把他取出來,這樣傳遞數據,雖然確實可以在新的頁面拿到并且進行渲染,但是問題是,如果進行刷新,我的數據將會丟失,只能返回上一頁,重新進入.所以這里的修改,采用拼接URL的方式.因為刷新不會改變的是路由的地址,所以我們采用跳轉路由通過拼接URL的方式,然后通過解析路由,在新頁面進行數據的請求.

const {id}=record;

than.props.dispatch(routerRedux.push({

pathname:`/person/druginfo/edit/${id}`,

? ? ? }))

router.js里面配置路由使這么寫

'/person/druginfo/:type/:id':{

component:dynamicWrapper(app, ['personrelease'], ()=>import('../routes/Person/PersonRelease/ReleaseInfo')),? ? ? },

在新的頁面進行解析路由,拿到我們需要的id,然后在本頁面進行數據請求

const pathToRegexp=require('path-to-regexp');

const match=pathToRegexp('/person/druginfo/:type/:id').exec(this.props.history.location.pathname)

this.props.dispatch({

type:'persondrug/getBase',

payload:{idCard:match[2],

},

});

2.父子組件之間的信息交流

子調父

父組件一般是向子組件傳遞數據,然后子組件拿到數據進行自己頁面的一個渲染,但是更多時候,我們需要將一些函數一起傳給子組件,比如:彈出一個Modal進行數據的填寫,然后關閉Model的這個操作我們需要父組件來控制,但是這個確定按鈕又是在子組件里面.這時候我們就需要將此類的函數向子組件傳遞.還有一種函數叫做回調函數,父組件什么時候需要傳遞回調函數給子組件呢,當父組件需要子組件的一些數據的時候,比如我們填好數據,點擊確定的時候將填寫好的數據返回給父組件,最終由父組件向后臺發送請求.

父控子

首先得明確一個問題,作為子組件一般我們不會再給他綁定model,因為我們遵守React的一個思想,就是一個Container,其余都是用作展示組件的component。而所謂的展示組件,就是他只接受數據和函數,而不進行相關的處理

① 父組件如何給子組件傳值和函數

②子組件如何返回數據給父組件

③如果我需要通過父組件來控制子組件的某些功能,怎么才能使用子組件的函數

父傳子代碼如下

在父組件我們要給子組件傳遞一個函數,用ref來綁定子組件

parentprops:{

title:'新增其他人員',

isVisible:false,

list:{},

name:'',

handleCancel:()=>

? ? ? ? ? ? ?? {

this.props.dispatch({

type:'otherpeople/changeVisibal',

payload:{isVisible:false},

? ? ? ? ? ? ? ? ?? })

? ? ? ? ? ? ?? },

onRef:(ref)=>{

this.ModalForm=ref

? ? ? ? ? ? ?? },

seachIdCard:(idCard)=>

? ? ? ? ? ? ?? {

this.props.dispatch({

type:'otherpeople/getBase',

payload:{

idCard,

? ? ? ? ? ? ? ? ? ? ?? },

? ? ? ? ? ? ? ? ?? });

? ? ? ? ? ? ?? },

? ? onRef :(ref) => {?

? ? ? ? ? ? ? ? ? ? ? ? this.ModalForm = ref

? ? ? ? ? ? ? ? ? ? },

<ModalFormparentprops={this.state.parentprops}/>

然后在子組建的componentDidMount里面綁定this

? ? ?componentDidMount(){

? ? ? ? ? this.props.parentprops.onRef(this)

? ? ? ? }

然后就在父組件里調用子組件的函數?

用法如下:?

this.ModalForm.check()?

3異步加載的antd Tree組件,設置了 defaultExpandAll 為true但是不起作用

應該是類似value和defaultValue的相似問題,而這個里defaultExpandAllRows?

就是像defaultValue那樣 只在第一次渲染的時候起作用

而很多時候我們的數據初始是空的

4.DatePick

// 限制可選日期范圍為,今天以前的日期不可選(今天仍可選)

disabledDate={

function disabledDate(current) {

// Can not select days before today

? ? return current && current.isBefore(moment(Date.now()).add(-1,'day'));

}

}

開始日期,結束日期

<DatePicker

? style={{width:'100%' }}? format="YYYY-MM-DD"

? disabledDate={currentDate =>

getFieldValue('validToDate') &&

moment(getFieldValue('validToDate')).isBefore(currentDate,'day')

}/>

<DatePicker

? style={{width:'100%' }}? format={dateFormat}? disabledDate={currentDate =>

getFieldValue('validFromDate') &&

moment(getFieldValue('validFromDate')).isAfter(currentDate,'day')

}/>

5.關于回傳數據(lov,select等等組件)

const {form } =this.props;

從lov的點擊事件獲取數據后如要放到表單中,某些字段需要初始化一下(getFieldDecorator)再setFieldsValue,否則會報警告

setFieldsValue

if (data) {

form.getFieldDecorator('materialId');

form.setFieldsValue({

nameZh: data.nameZh,

nameEn: data.nameEn,

materialTypeCode: data.materialTypeCode,

materialId: data.materialId,

});

}

6.Modal中的initialValue

1.當我們第一次點開Modal的時候, FormItem會得到一個initialValue,但是這個值只在組件掛載的時候執行了一次, 當我們再次打開Modal窗口的時候并不會更新。

好了發現問題所在了, 接下來就是解決了~

解決方法:

Modal窗口我們都有應用一個Visible來控制是否顯示, 我們只要利用這個值得變化就可以實現Modal組件的重新掛載了。

{

Visible&&<Modal....../>

}

7.Table組件rowSelection方法

<Table rowSelection={rowSelection} columns={columns} dataSource={data} />

在 <Table/> 組件中有 rowSelection={rowSelection} 方法,可以讓Table的第一列成為聯動的選擇框。

API中說到通過 rowSelection.selectedRowKeys 來控制選中項。比較坑的是,selectedRowKeys 控制的只是dataSource當前的順序編號。

一定要加上rowKey={record => record.id},唯一標識每一行的字段(可組合),且?selectedRowKeys?存的就是id才能正常顯示勾選狀態。后來經過多次調試發現很多BUG都跟一個參數有關,不然會導致聯動的選擇框狀態異常。

onSelectChange(selectedRowKeys,selectedRows) {

const {handelSelectRow}=this.props;

handelSelectRow(selectedRows);

this.setState({

selectedRowKeys:selectedRows.map(r=>r.num),

?? });

? }

<Table

rowSelection={{

selectedRowKeys,

onChange:this.onSelectChange,

? ? ?? }}

columns={columns}

dataSource={dataSource}

bordered

loading={loading}

scroll={{x:1600}}

pagination={pagination}

onChange={page=>onSearch(page)}

rowKey="num"

8.select下拉選擇器點擊時帶出多個數據

通常的select選擇器會點擊函數onSelect上只會帶出key和value,當是由于客戶需求,點擊時需要帶出其他數據。

我用dataRef={數據集合}把數據放到節點上。很多其他類似的情況都可以這么干。

queryFuzzyData({requestUrl,data}).then(result=>{

if(currentValue===value&&result) {

constres=[];

result.content.forEach(r=>{

res.push({

materialId:r.materialId,

nameZh:r.nameZh,

materialTypeCode:r.materialTypeCode,

salesUnit:r.packSize,

? ? ? ? ?? });

? ? ? ?? });

callback(res);

? ? ?? }

? ?? });

const options=data.map(d=><Optionkey={d.materialId}dataRef=lfb8e6o>{d.nameZh}</Option>);

<Select

showSearch

value={value}

defaultActiveFirstOption={false}

showArrow={showArrow}

filterOption={filterOption}

onSearch={this.handleSearch}

onChange={this.handleChange}

onSelect={onSelect}

notFoundContent={null}

>

{options}

</Select>? ? ? ? ? ? ? ? ? ? ? ??

handelSelect(data,option) {

const{form}=this.props;

const{dataref}=option.props;

if(dataref) {

form.getFieldDecorator('materialId');

form.setFieldsValue({

nameZh:dataref.nameZh,

materialTypeCode:dataref.materialTypeCode,

materialId:dataref.materialId,

salesUnit:dataref.salesUnit,

skuNum:dataref.skuNum,

? ?? });

?? }

? }

9.正確使用setState

react官方文檔中這樣介紹setState的

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

setState不會立即修改this.state,也就是說我們在調用setState的后,立即訪問this.state是不能取得最新的this.state的值的。這樣在一些特殊需求的時候可能會出現問題。但是我們可以通過使用setState回調函數的形式來使下面的代碼拿到最新的this.state的值。

updateState({target}) {

this.setState(prevState=>{

const updatedUser={...prevState.user, [target.name]:target.value};// 使用先前的state來構建新的state的值

doSomething(updatedUser);

return{user:updatedUser};

? });

}

10.React-router-dom 路由切換時,如何觸發 componentDidMount?

描述:

在react 項目中我們獲取遠程數據總是會放在 componentDidMount 里面做的。但是這樣的話只有在組件初始化的時候才會調用。

而有些路由類似于:

<Route path='/detail/:id' component={detail} />

然后我們有一些 用于跳轉的

<Link to="/detail/123"></Link>? <Link to="/detail/456"></Link>。。。componentDidMount(){const{ match,handleAjaxItem } =this.props;? ? handleAjaxItem(match.params.id);? }? render(){const{ item } =this.props;return(? ? ? <div className="site-content"><div className="container"><Item item={item}/></div></div>)? }

首次進入頁面例如 detail/123 的時候是沒問題,但往后切換到 detail/456 ,就不再走componentDidMount?了

解決方案有兩個:

1.componentWillReceiveProps,每次在這個函數做this.props和nextProps的相等判斷然后就可以調用想要調用的方法啦,但是(好像官網不推薦這么干了)

2.問題的本質是為我們這兩個路由頁面對應的都是一個detail組件,只要用key將組件加以區分,這樣react 就會知道這不是‘同一個組件’,于是會重新初始化,componentDidMount當然會再走一遍。我的方法是用函數把組件包裝一下

例如

// 這是正常的導出組件

exportdefaultDetail;

// 用函數包裝一下變成這樣

exportdefaultfunction(props) {

return<Detail{...props}key={props.match.params.id}/>

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容