获取并更新React中的表单数据

时间:2019-01-05 16:23:01

标签: reactjs graphql apollo-client

我正在使用React&Apollo客户端从GraphQL服务器获取数据。
现在,我在react中编写了以下组件。

  1. 用于列出所有项目的组件-工作正常。
  2. 用于创建项目的组件-运行中。
  3. 用于更新项目的组件-不起作用(不确定如何执行此操作)。

我有2个组件文件。

  1. UpdateAudio.js。
  2. AudioForm.js。

现在。

  1. 我需要从GraphQL服务器获取给定audioID的数据(将从路径参数中获取)。
  2. 然后将音频设置为状态。
  3. 并将音频状态传递给AudioForm组件。

我正在初始化状态为空白的音频。
我可以使用Query来获取数据,但是我不确定如何更新将被传递到AudioForm并进一步填充数据的音频状态。

UpdateAudio.js

import React, { Component, Fragment } from 'react';
import { withRouter } from 'react-router-dom';
import { Mutation, Query, graphql } from 'react-apollo';
import { UpdateAudioQuery, GetAudio } from '../query';
import { Button, Grid, LinearProgress } from '@material-ui/core';
import AudioForm from '../components/AudioForm';


class UpdateAudio extends Component {
    constructor(props) {
        super(props);
        this.state = {
            site: "5d517862-0630-431c-94b1-bf34de6bfd8b",
            audio: {
            site: "5d517862-0630-431c-94b1-bf34de6bfd8b",
            title: '',
            description: '',

            }
        };
        this.updateCache = this.updateCache.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    updateCache = (cache, { data }) => {
        if (data.createAudio.audio.guid) {
            console.log("redirecting...")
            this.props.history.push('/audios')
        }
    }

    handleChange = event => {
        const { name, value } = event.target;

        this.setState(prevState => ({
            audio: {
            ...prevState['audio'],
            [name]: value,
            }
        }));
    };

    render() {
        return (
            <Fragment>
                <AudioForm audio={this.state.audio} handleChange={this.handleChange}  />
                <Grid container alignItems="center" justify="center">
                    <Grid item>
                        <Mutation mutation={UpdateAudioQuery} update={this.updateCache}>
                            {(Update, {loading, data, error}) => {
                            if (loading) {
                                return <Button variant="contained" size="large" color="secondary" disabled>Save</Button>
                            }
                            else if (error) {
                                return <div>{error}</div>
                            }
                            else {
                                return <Button variant="contained" size="large" color="secondary" onClick={() => Update({variables: this.state.audio})}>Update</Button>
                            }
                            }}
                        </Mutation>
                    </Grid>
                </Grid>
            </Fragment>
        )
    }
}

UpdateAudio = withRouter(UpdateAudio)

export default graphql(GetAudio,
    {
        name:'Get',
        options: ownProps => ({ variables: {site: "5d517862-0630-431c-94b1-bf34de6bfd8b", guid: ownProps.match.params.guid} })
    })(UpdateAudio);

AudioForm.js

import React, {Fragment} from 'react';
import { TextField, Grid } from '@material-ui/core';


class AudioForm extends React.Component {

  render() {
    console.log(this.props.audio.title);

    return (
      <Fragment>
      <form  noValidate autoComplete="off">
        <Grid container spacing={24} alignItems="center" justify="center">
          <Grid item md={4} xs={12}>
            <TextField
              id="audio-title"
              name="title"
              label="Title"
              margin="normal"
              variant="outlined"
              InputLabelProps={{ shrink: true }}
              fullWidth
              defaultValue={this.props.audio.title}
              onChange={this.props.handleChange}
              required
            />
          </Grid>
          <Grid item md={4} xs={12}>
            <TextField
              id="audio-description"
              name="description"
              label="Description"
              margin="normal"
              variant="outlined"
              InputLabelProps={{ shrink: true }}
              fullWidth
              defaultValue={this.props.audio.description}
              onChange={this.props.handleChange}
            />
          </Grid>
        </Grid>
      </form>
      </Fragment>
    );
  }
}


export default AudioForm;

query.js

    import gql from 'graphql-tag';


    export const GetAudio = gql`
        query Get($site: String!, $guid: String!) {
        getAudio(site: $site, guid: $guid){
            guid
            siteGuid
            title
            description
        }
    }`

    export const UpdateAudio = gql`
        mutation Update($site: String!, $guid: String!, $title: String, $description: String) {
        updateAudio(
            input:{
                guid: $guid,
                site: $site,
                title: $title,
                description: $description
            }
        ) {
            audio{
                guid
                siteGuid
                title
                status
            }
        }
    }`;

1 个答案:

答案 0 :(得分:1)

我收到您的问题。 只是像下面这样查询。不要使用render props方法进行查询,因为您不能在那里执行setState。

以下方法的最佳位置是getDerivedStateFromProps函数。 在那里做这项工作。

client.query({
    query: GetAudio,
    variables: { site, guid }
  })
  .then((res) => {
    // check for response and do setState
    // example ... 
    const { site, title, description } = res;
    this.setState({ site, title, description });
  })
.catch( err => console.log(err));

也请查看官方文档中的链接 https://www.apollographql.com/docs/react/essentials/queries.html#manual-query

我读到,如果我听错了,我想你的问题要超过5倍,请原谅我。

保佑。