在反应组件之间发送数据
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});
假设 <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
回调。
抱歉冗长的代码片段,但有人可以帮助解决以下问题。我试图将另一个对象的一些数据带入我的突变中,但是当表单提交数据时,即使表单中显示了正确的值,数据也不会随之而来。如果你看下面的代码,你可以看到我已经将突变包装在用户查询中并使用 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});
假设 <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
回调。