Абстрактный клиент за <ApolloConsumer> - PullRequest
0 голосов
/ 24 декабря 2018

Я использую Formik для проверки данных формы.В качестве дополнительной проверки я проверяю, существует ли электронная почта пользователя в базе данных.У меня работает этот код, но мне не нравится его встроенный.Есть ли лучший способ написать это, чтобы валидация не была встроенной?Я не понимаю, как пройти через клиента.

    <Form className="form">
            <ApolloConsumer>
                {client => (
                    <Field className="text-input" type="email" name="email" placeholder="Email" validate={async (value) => {
                        let error

                        const response = await client.query({
                            query: USER_EXISTS,
                            variables: {
                                query: value
                            }
                        })

                        console.log(response.data.userExists)

                        if (response.data.userExists) {
                            error = 'Email taken'
                        }

                        return error
                    }} />
                )}
            </ApolloConsumer>
      <Form>

Например, что-то вроде этого:

<ApolloConsumer>
      {client => (
             <Field className="text-input" type="text" name="username" placeholder="Username" validate={this.validateUsername(client)} />
      )}
</ApolloConsumer>


validateUsername = async (value, client) => {
    let error

    const response = await client.query({
        query: USER_EXISTS,
        variables: {
            query: value
        }
    })

    console.log(response.data.userExists)

    if (response.data.userExists) {
        error = 'Username taken'
    }

    return error
}

1 Ответ

0 голосов
/ 24 декабря 2018

Кажется, что вам нужен HOC (High Order Component) - функция, которая возвращает компонент, поэтому для абстрагирования вашей функции вам нужно что-то вроде

const withApolloClient = (ConnectedComponent) => class extends React.Component {
  render() {
    return (
      <ApolloConsumer>
         {client => <ConnectedComponent {...this.props} client={client} />
      </ApolloConsumer>
    );
  }
}

, как только вы настроите withApolloClient HOCтак что вы можете использовать его следующим образом

// create a field component with validation logic
class FieldWithValidationApolloClient extends React.Component {
  async validateUsername() {
    let error;
    const { client, field } = this.props; // get apollo client injected by withApolloClient Hoc
    const { value } = field; // get value from the field


    const response = await client.query({
      query: USER_EXISTS,
      variables: {
        query: value
      }
    })

    console.log(response.data.userExists)

    if (response.data.userExists) {
      error = 'Username taken';
    }

    return error;
  }

  render() {
    return (
      <Field {...this.props} validate={this.validateUsername(client)} />
    );
  }
}

И, наконец, просто реализовать свой компонент

// import your withApolloClient component file
import withApolloClient from './withApolloClient';
import FieldWithApolloClient from './FieldWithValidationApolloClient';
const FieldWithApollo = withApolloClient(FieldWithApolloClient);

class YourFormComponent extends React.Component {
  render() {
    return (
      <form>
        <FieldWithApollo className="text-input" type="text" name="username" placeholder="Username" />
      </form>
    );
  }
}
<form>

</form>

помните, что {...this.props} распространит все объявленные атрибуты в компонент тега

Надеюсь, это поможет вам.

...