美文网首页纵横研究院React技术专题社区
使用react开发的经验总结(持续更新)

使用react开发的经验总结(持续更新)

作者: katherine_a120 | 来源:发表于2019-05-26 21:59 被阅读38次

    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={d}>{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}/>

    }

    相关文章

      网友评论

        本文标题:使用react开发的经验总结(持续更新)

        本文链接:https://www.haomeiwen.com/subject/qbfqtctx.html