在反应组件之间发送数据

Sending data between react components

抱歉冗长的代码片段,但有人可以帮助解决以下问题。我试图将另一个对象的一些数据带入我的突变中,但是当表单提交数据时,即使表单中显示了正确的值,数据也不会随之而来。如果你看下面的代码,你可以看到我已经将突变包装在用户查询中并使用 me.address 等来显示 data.What 我做错了吗......在这里拉我的头发

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 };
const res = await createJob();

你不应该给 createJob 函数添加参数吗?

在这种情况下,它将是 await createJob({variables: this.state});

well examples in docs tell so

假设 <User/> 包含查询组件和 rendes 子项...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 }) => (

您应该将此功能(表单+突变)放在单独的组件中以管理内部状态(将地址作为道具传递)更重要的是不要重新渲染所有这个 structures/components. 组件在反应中很便宜 ;)

正如 Józef 所说,'compose' 随叫随到的变异输入会更容易,例如:

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

await-ing 没有意义,因为您应该使用 onCompleted 回调。