首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React/ React - Hooks :需要在React Hooks组件中运行函数onLoad

React/ React - Hooks :需要在React Hooks组件中运行函数onLoad
EN

Stack Overflow用户
提问于 2019-06-18 22:27:32
回答 1查看 22.3K关注 0票数 7

我有一个父组件,它有一个在电子邮件输入字段上运行验证的函数,并将该函数作为道具向下传递给实际包含需要验证的输入字段的子组件。验证是有效的,我现在唯一的问题是验证不会在加载时运行,所以即使在输入字段中预先填充了用户电子邮件,验证的默认状态也被设置为失败,因此用户必须单击输入字段并单击输出才能触发onBlur函数,从而触发验证。我不确定如何使用react钩子在加载时运行函数,因为我对使用它们还很陌生。

Parent Component

代码语言:javascript
复制
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { Row, Col } from 'antd'
import * as actions from '../../actions'
import { tableColumnProps } from '../../propTypes'
import Section from '../../components/layout/Section'
import CustomerDetails from '../../components/orders/CustomerDetails'
import AccountDetails from '../../components/orders/AccountDetails'
import ExistingServices from '../../components/orders/ExistingServices'
import OfferBundlesFilters from '../../components/orders/OfferBundlesFilters'
import OfferBundlesTable from '../../components/orders/OfferBundlesTable'
import OffersHeader from '../../components/orders/OffersHeader'

function validateEmail(value) {
  const errors = { hasError: false }
  if (value === '') {
    errors.email = 'Email address or Email Opt Out is required'
    errors.hasError = true
    return errors
  }

  if (!/\S+@\S+\.\S+/.test(value)) {
    errors.email = 'Email address is invalid'
    errors.hasError = true
    return errors
  }
  return errors
}

export class OffersPage extends Component {
  constructor(props) {
    super(props)

    this.state = {
      customerEmail: {},
      disableEmailValidation: false,
      emailValidation: {
        isValid: false,
        validationError: ''
      }
    }
  }

  componentDidMount() {
    this.props.getOffers()
  }

  toggleDisableInput = value => {
    this.setState({ disableEmailValidation: value })
  }

  removeEmailValidationError = () => {
    this.setState({
      emailValidation: {
        isValid: true,
        validationError: ''
      }
    })
  }

  checkIfCustomerEmailIsValid = inputValue => {
    const validationResult = validateEmail(inputValue)
    if (validationResult.hasError === true) {
      this.setState({
        emailValidation: {
          isValid: false,
          validationError: validationResult.email
        }
      })
    } else {
      this.removeEmailValidationError()
    }
  }

  getEmailValue = email => {
    if (email.hasError) {
      this.setState({ customerEmail: email })
    }
  }

  render() {
    const {
      customer,
      offers,
      services,
      // selectOffer,
      selectedOffer = {},
      offerColumns,
      filters,
      updateFilter,
      updateCustomer
    } = this.props

    return (
      <Fragment>
        <Row gutter={48}>
          <Col span={24}>
            <OffersHeader
              customer={customer}
              onPaidByChange={updateCustomer}
            />
          </Col>
        </Row>
        <SectionRow>
          <div>
            <Section title="Customer">
              <CustomerDetails
                customer={customer}
                getEmailValue={this.getEmailValue}
                checkIfCustomerEmailIsValid={this.checkIfCustomerEmailIsValid}
                emailValidation={this.state.emailValidation}
                disableEmailValidation={this.state.disableEmailValidation}
                toggleDisableInput={this.toggleDisableInput}
                removeEmailValidationError={this.removeEmailValidationError}
              />
            </Section>
            <Section title="Account Information">
              <AccountDetails />
            </Section>
          </div>
          <div>
            <Section title="Existing Services">
              <ExistingServices services={services} />
            </Section>
          </div>
        </SectionRow>
        <Row gutter={48}>
          <Col span={24}>
            <StyledFiltersSection title="Filters">
              <OfferBundlesFilters
                filters={filters}
                onFilterChange={updateFilter}
              />
            </StyledFiltersSection>
          </Col>
        </Row>
        <Row gutter={48}>
          <Col span={24}>
            <Section title="Offers">
              <OfferBundlesTable
                columns={offerColumns}
                bundles={offers}
                viewedOfferIds={[selectedOffer.OfferId]}
                onBundleSelect={this.handleSelectOffer}
              />
            </Section>
          </Col>
        </Row>
      </Fragment>
    )
  }
}

const mapStateToProps = state => ({
  customer: state.customer.details,
  offers: state.offers.all,
  offerColumns: state.offers.tableColumns,
  selectedOffer: state.offers.selectedOffer,
  filters: Object.values(state.offers.filters),
  services: state.offers.services,
  pages: state.navigation
})

const mapDispatchToProps = {
  getOffers: actions.getOffers,
  selectOffer: actions.selectOffer,
  updateFilter: actions.updateOfferFilters,
  updateCustomer: actions.updateCustomer
}

OffersPage.propTypes = {
  customer: PropTypes.object,
  filters: PropTypes.arrayOf(PropTypes.object),
  updateFilter: PropTypes.func.isRequired,
  updateCustomer: PropTypes.func.isRequired,
  getOffers: PropTypes.func.isRequired,
  offers: PropTypes.arrayOf(PropTypes.object),
  offerColumns: tableColumnProps,
  selectOffer: PropTypes.func.isRequired,
  selectedOffer: PropTypes.object,
  services: PropTypes.object,
  location: PropTypes.object,
  history: PropTypes.object
}

OffersPage.defaultProps = {
  customer: null,
  offers: []
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(OffersPage)

Child Component

代码语言:javascript
复制
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {
  Col, Row, Icon, Input, Tooltip
} from 'antd'
import Checkbox from '../elements/Checkbox'
import Markup from '../core/Markup'

const CustomerDetails = ({
  customer,
  checkIfCustomerEmailIsValid,
  emailValidation,
  toggleDisableInput,
  disableEmailValidation,
  removeEmailValidationError
}) => {
  const { contact = {}, account = {}, site = {} } = customer || {}
  const [inputValue, setInputValue] = React.useState(contact.email)

  function onBlur(e) {
    checkIfCustomerEmailIsValid(e.target.value)
  }

  function clearInput() {
    setInputValue('')
  }

  function handleInputChange(event) {
    setInputValue(event.target.value)
  }

  return (
    <Container>
        <Row>
          <Col span={10}>
            <h4>
              PRIMARY CONTACT EMAIL &nbsp;
            </h4>
          </Col>
        </Row>
        <Row>
      <Row>
        <Col span={8}>
          <StyledInput
            value={inputValue}
            onChange={handleInputChange}
            disabled={disableEmailValidation}
            onBlur={onBlur}
            isError={!emailValidation.isValid}
          />
          {!emailValidation.isValid && (
            <ErrorDiv>{emailValidation.validationError}</ErrorDiv>
          )}
        </Col>
        <Col span={2} />
        <Col span={8}>
          <StyledCheckbox
            onChange={handleOptOut}
            checked={disableEmailValidation}
            isError={!emailValidation.isValid}
          />{' '}
          EMAIL OPT OUT{' '}
        </Col>
      </Row>
    </Container>
  )
}

CustomerDetails.propTypes = {
  customer: PropTypes.object,
  emailValidation: PropTypes.object,
  checkIfCustomerEmailIsValid: PropTypes.func,
  toggleDisableInput: PropTypes.func
}

CustomerDetails.defaultProps = {
  customer: {}
}


const ErrorCheckbox = ({ isError, ...remainingProps }) => (
  <Checkbox {...remainingProps} />
)

const ErrorInput = ({ isError, ...remainingProps }) => (
  <Input {...remainingProps} />
)

const StyledCheckbox = styled(ErrorCheckbox)`
  &&& {
    background: white;

    input + span {
      width: 35px;
      height: 35px;
      border: 2px solid
        ${({ theme, isError }) =>
    isError ? theme.colors.danger : theme.colors.black};
    }

    input + span:after {
      width: 12.5px;
      height: 20px;
    }

    input:focus + span {
      width: 35px;
      height: 35px;
    }
  }
`

const StyledInput = styled(ErrorInput)`
  max-width: 100%;
  background: white;

  &&& {
    border: 2px solid
      ${({ theme, isError }) =>
    isError ? theme.colors.danger : theme.colors.black};
    border-radius: 0px;
    height: 35px;
  }
`

ErrorInput.propTypes = {
  isError: PropTypes.bool
}

ErrorCheckbox.propTypes = {
  isError: PropTypes.bool
}

const ErrorDiv = styled.div`
  color: #d11314;
`

const ErrorContainer = styled.div`
  span {
    text-align: center;
  }
`

export default CustomerDetails
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-18 23:03:21

尝试将开模糊代码粘贴到效果中。我看到您使用的是e.target.value,但是您已经使用useState显式设置值,所以请使用inputValue

代码语言:javascript
复制
React.useEffect(() => checkIfCustomerEmailIsValid(inputValue), [])

useEffect所做的是,当第二个参数中的变量发生变化时,执行第一次渲染和每一次其他渲染中提供的函数。因为我们提供了一个空数组,所以它只会执行一次--当组件最初呈现的时候。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56651399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档