Отправка данных между реагирующими компонентами - PullRequest
2 голосов
/ 02 мая 2020

Извините за длинный фрагмент кода, но кто-нибудь может помочь с приведенным ниже. Я пытаюсь внести некоторые данные из другого объекта в свою мутацию, но когда форма отправляет данные, они не go, хотя правильные значения отображаются в форме. Если вы посмотрите на приведенный ниже код, то увидите, что я обернул мутацию в запросе пользователя и использовал me.address et c для отображения данных. Что я делаю не так ... потянув меня за волосы здесь

import styled from 'styled-components'
import React, { Component } from 'react';
import { Mutation } from 'react-apollo';
import User from './User';
import gql from 'graphql-tag';
import Router from 'next/router';
import Form from './styles/Form';
import Ghost from './styles/Ghost';
import Error from './ErrorMessage';

const Div = styled.div `
display: flex;
justify-content: center;
`;

const Container = styled.div `
    max-width: 1000px;
`;

const SINGLE_USER_QUERY = gql`
  query SINGLE_USER_QUERY($id: ID!) {
    user(where: { id: $id }) {
      id
      address
      lat
      lng
    }
  }
`;

const CREATE_JOB_MUTATION = gql`
  mutation CREATE_JOB_MUTATION(
    $name: String
    $address: String
    $email: String
    $description: String!
    $image: String!
    $cube: Int!
    $reqPickup: String
    $instructions: String!
    $feedback: String
    $lat: String
    $lng: String
    $pickup: DateTime
    $charges: Int
    $price: Int
  ) {
    createJob(
    name: $name
    address: $address
    email: $email
    description: $description
    image: $image
    cube: $cube
    reqPickup: $reqPickup
    instructions: $instructions
    feedback: $feedback
    lat: $lat
    lng: $lng
    pickup: $pickup
    charges: $charges
    price: $price
    ) {
      id
    }
  }
`;


class CreateJob extends Component {
    state = {
      name: '',
      address: '',
      email: '',
      description: '',
      image: '',
      cube: '',
      reqPickup: '',
      instructions: '',
      feedback: '',
      lat: '',
      lng: '',
      pickup: '',
      charges: '0',
      price: '0',
    };


    handleChange = (e) => {
      const { name, type, value } = e.target;
      const val = type === 'number' ? parseFloat(value) : value;
      this.setState({ [name]: val});
    };    

    componentDidMount() {
      console.log(this.state);
    };

    uploadFile = async e => {
      const files = e.target.files;
      const data = new FormData();
      data.append('file', files[0]);
      data.append('upload_preset', 'sickfits');

      const res = await fetch('https://api.cloudinary.com/v1_1/wesbostutorial/image/upload', {
        method: 'POST',
        body: data,
      });
      const file = await res.json();
      this.setState({
        image: file.secure_url,
        largeImage: file.eager[0].secure_url,
      });
    };

    render() {
        return (


          <Div>
          <Container>
          <User>
      {({ data }) => {
        const me = data ? data.me : null
        return (
          <Mutation mutation={CREATE_JOB_MUTATION} variables={this.state}>
            {(createJob, { loading, error }) => (
          <Form
          data-test="form"
          onSubmit={async e => {
            // Stop the form from submitting
            e.preventDefault();
            // call the mutation
            console.log(this.state);
            this.setState({ address: me.address });
            const res = await createJob();
            // change them to the single job page
            console.log(res);
            Router.push({
              pathname: '/job',
              query: { id: res.data.createJob.id },
            });
          }}>
                <Error error={error} />
            <fieldset disabled={loading} aria-busy={loading}>

                <label htmlFor="description"> 
                    Describe your waste: Just a few words to describe the materials.
                    <input
                    type="text"
                    id="description"
                    name="description"
                    placeholder="eg: wood, bricks, old kitchen tops and a fridge"
                    required
                    value={this.state.description}
                    onChange={this.handleChange}
                  />
                    </label>

                    <label htmlFor="instructions"> 
                    Instructions: Any specific instructions such as desired collection time or access info.
                    <input
                    type="text"
                    id="instructions"
                    name="instructions"
                    placeholder="Instructions for the collection team"
                    required
                    value={this.state.instructions}
                    onChange={this.handleChange}
                  />
                    </label>


                    <label htmlFor="address"> 
                    Address:
                    <input
                    type="text"
                    id="address"
                    name="address"
                    required
                    defaultValue={me.address}
                    onChange={this.handleChange}
                  />
                    </label>


                    <p
                    style={{
                        textAlign: 'center',
                      }}
                    >Click the submit button and we'll come back to you in just a few moments with a quote and collection time options</p>
                    <div
                     style={{
                        display: 'flex',
                        margin: 'auto',
                        justifyContent: 'center',
                      }}
                    >
                    <button
                    type="submit">SUBMIT</button>
                    </div>
                </fieldset>
            </Form>
            )}
            </Mutation>
            )
          }}
        </User>
            </Container>
          </Div>
        );
    }
}

export default CreateJob;
export { CREATE_JOB_MUTATION };

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Предполагается, что <User/> содержит компонент запроса и возвращает детей ... data будет содержать результат (когда данные поступят), который вы хотите сохранить в состоянии ...

  {({ data }) => {
    // is data from query ready?
    const me = data ? data.me : null;
    // prevent looping (setState > rerendering)
    if( me && (me.address!=this.state.address) ) {
      setState( {address: me.address} )
    }
    return (
      <Mutation mutation={CREATE_JOB_MUTATION} 
        variables={this.state}
        onCompleted={(data)=>{
          console.log("mutated, result: ", data);
          // Router.push
        }}
      >
        {(createJob, { loading, error }) => (

Вы должны поместить эту функциональность (форма + мутация) в отдельный компонент для управления состоянием внутри (передать адрес как пропеллер) и, что более важно, не перерисовывать все эти структуры / компоненты. Компоненты дешевы в реакции ;)

Как сказал Юзеф, было бы легче «составить» ввод мутаций при вызове, например:

 createJob({variables: { ...this.state, address: me.address} })

await - не имеет смысла, так как вы должны использовать onCompleted обратный звонок.

0 голосов
/ 02 мая 2020
const res = await createJob();

Разве вы не должны добавлять параметр в createJob функцию?

В этом случае это будет await createJob({variables: this.state});

хорошо, примеры в документах говорят об этом

...