重构反应代码以提高性能

时间:2020-07-19 12:35:53

标签: javascript reactjs react-native react-redux

我是React编码方面的新手,我刚刚加入一个新组织,需要将该代码发送以供审核。该功能正常工作,但在我看来,组件中的代码变得很冗长, Submithandler方法使我多次迭代数组,但我不知道如何进行其他操作。有什么方法可以缩短代码以使其看起来更好并提高性能?目前花了很长时间单击提交后需要显示数据的时间,看起来迭代oof数组需要时间。

此外,如果我在单击“提交”按钮后关闭浏览器,则仍在执行ajax待处理的请求。我要结束请求并在我关闭浏览器或导航到其他页面后停止加载。myRequestor是第三方组织的可用于发送请求的库。请帮助我缩短代码并解决未解决的ajax请求问题。下面是我尝试执行的代码。

const propTypes = {
  name: PropTypes.string,
  tenant: PropTypes.arrayOf(PropTypes.any),
  myRequestor: PropTypes.object, // eslint-disable-line react/forbid-prop-types
  };


let myRequestor = null;

const CallerUtil = () => {
myRequestor = React.useContext(MyRequestorContext);
return <ApplicationLoadingOverlay isOpen backgroundStyle="clear" />;
}


class ReadinessComponent extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        body: '',
        tenant: null,
        error: null,
        errorMsg: '', 
        isOpen: false,
        showTable: false,
        isInvalid: false,
        isLoading: false,
        tenantId: '',
        items: [],
        tenantItems : null
    };

    this.onChangeTenantDropDown = this.onChangeTenantDropDown.bind(this);
    this.onSubmitHandler = this.onSubmitHandler.bind(this);
    this.onChangeHandler = this.onChangeHandler.bind(this);
    this.tenantIdHandler = this.tenantIdHandler.bind(this);
    this.onClose = this.onClose.bind(this);
    this.addNewTenant = this.addNewTenant.bind(this);
    this.fetchInitial = this.fetchInitial.bind(this);
   }

componentDidMount() {
  this.mounted = true;
  this.setState({ isLoading: true });
  this.fetchInitial();

  }
componentWillUnmount(){
    
    this.mounted = false;

  }

onChangeTenantDropDown(value) {
    this.setState({
        tenant: value,
    });

  const info = this.state.tenantItems.find(function (t) { return t.name == value })
  this.setState({
    tenantId: info.id,
  });

}

  onSubmitHandler() {
    if (this.state.body == '') {
      this.setState({ isInvalid: true });
      return;
    }
    this.setState({ isLoading: true });
    const params = {
      "tenantId": this.state.tenantId,
      "tenantShortName": this.state.tenant,
      "contactName": this.state.body
    }

    const { request } = myRequestor.get({
      url: '/getReadinessCheck',
      params: params,
    });

   // request.then(async ({ data }) => {
      request.then(({ data }) => {
      console.log(this.mounted);
      if (!this.mounted) {
        this.setState({ isLoading: false });
        return;
      }
        
      console.log(data);
      
      let abc = data.find(vrsn => vrsn.name === 'TENANT_ERROR');         
      if (abc === undefined) {
        this.setState({ error: 'Failure', errorMsg:'Invalid Tenant',isLoading: false, isOpen: true, showTable: false, body: '', tenantId: ''});
        return;
      }
      let readinessResp = data.map(version => (version.latest === true ? { ...version, name: version.name.concat('_LATEST') } : version))
      readinessResp.sort(function (a, b) {
        var textA = a.name.toUpperCase();
        var textB = b.name.toUpperCase();
        return textA.localeCompare(textB);
      });

      this.setState({ items: readinessResp, error: 'Success', showTable: true, isLoading: false });
    }).catch(error => {
        this.setState({ error: 'Failure', errorMsg:'Failure', isLoading: false, isOpen: true, showTable: false ,body: '', tenantId: '' });
      });
    
  }


onChangeHandler(event) {
    this.setState({
        body: event.target.value,
    });
}

tenantIdHandler(event) {
  this.setState({
    tenantId: event.target.value,
  });
}

onClose() {
    this.setState(prevState => ({
        isOpen: !prevState.isOpen,
    }));
}


addNewTenant(shortName,tenantId){
  const newTenantShortName = shortName;
  const newTenantId = tenantId;
  const newTenant = {'name':newTenantShortName, 'id':newTenantId};
  this.setState({
    tenantItems: [...this.state.tenantItems, newTenant]
});     

}

fetchInitial() {
  this.setState({ isLoading: true });
  const { request } = myRequestor.get({
    url: '/tenants'
  });
   
  request
  .then(({ data }) => {
    if(data[0].hasOwnProperty("error")){
      this.setState({ error: 'Failure', errorMsg:data[0]['error'], isOpen: true, isLoading: 
   false,tenantItems: [{'name':'Default', 'id':'Default'}]});
      return;
    }

    let tenantsList = data;
    let tenants =[];
    tenantsList.map(tenant => ( tenants.push({'name':tenant.shortName, 'id':tenant.key})))

  this.setState({
    tenantItems: tenants,isLoading: false
  });
  })
  .catch((error) => {
    this.setState({ error: 'Failure', isOpen: true, isLoading: false});
  });
  }


  render() {
      const {
   error, isOpen, body,showTable
       } = this.state;

if (this.state.tenantItems === null) {
  return <CallerUtil />;
  }

if(this.state.isLoading){
    return <ApplicationLoadingOverlay isOpen backgroundStyle="clear" />;
}

if (showTable) {
    return (<div>
    <h1>Readiness Status</h1>
    <ReadinessComponentView readinessInfo={this.state.items} /></div>);
}

return (
  <div className="ruleSupportEvaluation">
    <Grid>
      <Grid.Row>
        <Grid.Column>
          <Heading level={1}>Readiness Check</Heading>
        </Grid.Column>
      </Grid.Row>
      <Grid.Row>
        <Grid.Column className="ruleSupportEvaluation" large={3} medium={3}>
          <div>
            <Heading className="info" level={3}>About</Heading>
            <Divider />
            <Text className="description" fontSize={18}>
              Readiness Check
            </Text>
          </div>
        </Grid.Column>
        <Grid.Column className="ruleSupportEvaluation" large={8} medium={8}>
          <div>
            <div className="readinessComponent">
            <Tenant
              tenant={this.state.tenantItems}
              change={this.onChangeTenantDropDown}
            />
            <ModalManagerExample addNewTenant={this.addNewTenant} />
            </div>
            <InputField type="text" label="Tenant-Id" value={this.state.tenantId} placeholder="Tenant Id" onChange={this.tenantIdHandler}/>
            <InputElement isInvalid ={this.state.isInvalid} change={this.onChangeHandler} value={body} />                
            <Submit click={this.onSubmitHandler} />
            
            {error === 'Failure' &&
              (
                <Notification
                  errorMessage={this.state.errorMsg}
                  close={this.onClose}
                  isOpen={isOpen}
                />
              )
             }
          </div>
        </Grid.Column>
      </Grid.Row>
    </Grid>
  </div>
);
     }
 }

ReadinessComponent.propTypes = propTypes;

export default ReadinessComponent;

1 个答案:

答案 0 :(得分:1)

@charlietfl提到-codereview.stackoverflow.com可能是您最好的选择,

第一个快速获胜的方法是从构造函数中提取所有.bind(this)的东西,并为这些方法在类中定义它们,如下所示:

之前:

onChangeTenantDropDown(value) {
    this.setState({
        tenant: value,
    });

  const info = this.state.tenantItems.find(function (t) { return t.name == value })
  this.setState({
    tenantId: info.id,
  });

}

之后:

onChangeTenantDropDown = (value) => {
    this.setState({
        tenant: value,
    });

  const info = this.state.tenantItems.find(function (t) { return t.name == value })
  this.setState({
    tenantId: info.id,
  });

}

请注意箭头功能。

您也可以直接将状态设置为类属性,因此从定义状态的位置删除this.并将其移至构造函数之外,即:

class ReadinessComponent extends Component {
  state = {
        body: '',
        tenant: null,
        error: null,
        errorMsg: '', 
        isOpen: false,
        showTable: false,
        isInvalid: false,
        isLoading: false,
        tenantId: '',
        items: [],
        tenantItems : null
    };
    ...
}

现在您也可以完全删除构造函数了:)

希望这能使您至少部分到达那里

如果您是新手,完全建议学习Hooks,它确实可以帮助清理此类组件-以下是一些链接:

编辑

针对您的评论:

onSubmitHandler = async () => {
    const { body, tenantId, tenant: tenantShortName, body: contactName } = this.state;
    if (!body) {
        this.setState({ isInvalid: true });
        return;
    }

    this.setState({ isLoading: true });

    const params = {
        tenantId,
        tenantShortName,
        contactName,
    };

    try {
        const { request } = myRequestor.get({
            url: '/getReadinessCheck',
            params,
        });
        
        const { data } = await request;

        if (!this.mounted) {
            this.setState({ isLoading: false });
            return;
        }

        let abc = data.find((vrsn) => vrsn.name === 'TENANT_ERROR');
        if (abc === undefined) {
            this.setState({
                error: 'Failure',
                errorMsg: 'Invalid Tenant',
                isLoading: false,
                isOpen: true,
                showTable: false,
                body: '',
                tenantId: '',
            });
            return;
        }
        let readinessResp = data.map((version) =>
            version.latest === true ? { ...version, name: version.name.concat('_LATEST') } : version,
        );
        readinessResp.sort(function (a, b) {
            var textA = a.name.toUpperCase();
            var textB = b.name.toUpperCase();
            return textA.localeCompare(textB);
        });

        this.setState({ items: readinessResp, error: 'Success', showTable: true, isLoading: false });

    } catch (err) {
        this.setState({
                error: 'Failure',
                errorMsg: 'Failure',
                isLoading: false,
                isOpen: true,
                showTable: false,
                body: '',
                tenantId: '',
            });
    }
};