【问题标题】:Sending data between react components在反应组件之间发送数据
【发布时间】:2020-08-17 08:03:00
【问题描述】:

对于冗长的代码 sn-p 感到抱歉,但任何人都可以在下面提供帮助。我正在尝试将来自另一个对象的一些数据带入我的突变中,但是当表单提交时,即使表单中显示了正确的值,数据也不会随之而来。如果您查看下面的代码,您可以看到我已经将突变包装在用户查询中并使用 me.address 等来显示数据。我做错了什么......在这里拉我的头发

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 };

【问题讨论】:

  • 您是否控制台记录了您的状态以查看您的状态是否充满数据?
  • console.log(this.state); this.setState({ 地址: me.address });以上两行来自我的调试工作。 console.log 查看我的状态(null)和 setstate 尝试发送数据。

标签: javascript reactjs graphql next.js react-apollo


【解决方案1】:

假设&lt;User/&gt; 包含查询组件并渲染子代...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 }) => (

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

正如 Józef 所说,在调用时“组合”变异输入会更容易,例如:

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

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

【讨论】:

    【解决方案2】:
    const res = await createJob();
    

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

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

    well examples in docs tell so

    【讨论】:

    • 我不确定。以前从未使用过 Mutation 组件。但是文档确实告诉您也可以像他一样将变量作为道具传递。
    • 变量可以作为Mutation 组件的道具,或mutate 函数的参数,或两者兼而有之。如果两者都提供,它们将被合并到一个 variables 对象中。 Mutation 组件和 useMutation 钩子都是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2020-02-16
    • 1970-01-01
    • 2021-08-24
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多