用react重构项目遇到的问题汇集

507 阅读2分钟

公司一个运营系统平台IDM一直在用jquery做迭代,每次新增需求都很让人头疼,现在哪里还有人写jq啊,刚好接近年底项目没那么忙了,公司新项目都用的vue,以前不选react是因为类组件真的比vue复杂很多,现在react hooks出来了,刚好学习了一下,所以就直接用react重构了,没错,选型真的很随意😄

以下是用react开发中遇到过的问题,虽然现在看来都是一些浅知识,但对于新手来说也是一种宝贵的经验吧!

这是我在开发中遇到了就随意记录下来的,所以没有什么特别详细的解答

一、多个地方用到了客户下拉列表,是否需要放在redux store中呢?如果要的话,什么时候更新数据呢?

解决方案:把请求放在一个文件里,分别在需要的组件页面导入调用(最简单的方法)

二、Transfer 出现报错 Each child in a list should have a unique "key" prop.

解决方案:

const [sourceData, setSourceData] = useState<sourceDataType []>([]);
const newData = [];
 for (let i = 0; i < res.length; i += 1) {
       newData.push({ ...res[i], key: res[i].clientId });
     }
setSourceData(newData)

对Transfer 的sourceData增加key字段,注意render返回label,value,key

image.png

三、Form组件升级版,传入自定义组件或元素并渲染,如何做?

(1)在已有的FormItem页面props中增加 renderTmp

image.png

image.png

image.png 注意:当type为other,如果传入的元素包含Form.Item,那么该页面要去掉Form.Item上的name

image.png

调用组件页面

image.png

newFormoptions中传入renderTmp:

image.png

注意:这里如果不用Form.Item包裹一下,会报错[antd: Form.Item] children is array of render props cannot have name.

四、如何在Typescript中定义Promise的返回值类型?

(1)通过 Promise 的构造函数,声明返回值的泛型类型。

image.png

(2)修改 reslove的类型定义

image.png

五、Table报错 Each child in a list should have a unique "key" prop.

解决方法:

image.png 或者 rowKey="uniqueid"

六、setState 如何异步转同步?

setTomeout? Promise?

七、 react hook useHistory(),state传值,刷新后state丢失?该如何解决?

用search传参? 用state搭配sessionStorage传参数? 还有其他方式吗?

八、form表单如何选中checkbox?

解决方案:在Form.item上增加valuePropName="checked"

<Form.Item label="产品体验" name="allowApply" valuePropName="checked">
     <Checkbox checked={initialValues.allowApply}>
         允许申请
     </Checkbox>
  </Form.Item>

九、父子组件相互调用的方法

(1)子组件调用父组件 父组件直接把方法传给子组件,子组件可直接调用

父组件

import Children from ''
const Father=()=>{
   //方法
    const getInfo=()=>{
         console.log('我被调用拉!')
    }
    return ()=>{
        <div>
            <Children 
                getInfo={getInfo}
            />
        </div>
    }
}
export default Father

子组件

const Children=(props:any)=>{
const { getInfo }=props
    return ()=>{
        <div>
            <span onClick={getInfo}>调用父组件函数</span>
        </div>
    }
}
export default Children

(2)、父组件调用子组件的方法

//父组件  需要引入useRef
import {useRef} from 'react'

const Father=()=>{

    const childRef=useRef();
    const onClick=()=>{
        childRef.current.getInfo();
    }
    return ()=>{
        <div>
            <Children 
                ref={childRef}
            />
            <span onClick={onClick}>调用子组件函数</span>
        </div>
    }
}
export default Father

//子组件 
//需要引入useImperativeHandle,forwardRef
import {useImperativeHandle,forwardRef} from 'react'
const  Children=(ref,props)=>{
    useImperativeHandle(ref, () => ({
        getInfo:()=>{
         console.log('需要处理的数据')
        }
    }))
    return ()=>{
        <div></div>
    }
}
Children = forwardRef(Children);
export default Children 

useImperativeHandle 需要配合着 forwardRef 使用,要不就会出现以下警告

Warning: Function components cannot be given refs. Attempts to access thisref will fail. Did you mean to use React.forwardRef()?

十、内存泄漏隐患

报错:

image.png

我们不能在组件销毁后设置state,防止出现内存泄漏的情况 关于react中切换路由时报以上错误,实际的原因是因为在组件挂载(mounted)之后进行了异步操作,比如ajax请求或者设置了定时器等,而你在callback中进行了setState操作。当你切换路由时,组件已经被卸载(unmounted)了,此时异步操作中callback还在执行,因此setState没有得到值 无需清除的 effect:发送网络请求,变更DOM,记录日志都是常见的无需清除的操作。 需要清除的 effect:订阅外部数据源。这种清除是很重要的,可以防止引起内存泄漏