我正在使用 { useReducer } 来管理我的表单状态。但我有两个单独的处理程序
- handleChange() = 用于输入更改(这个按预期工作)
const handleChange = async (e) => {
dispatch({field: e.target.name, value: e.target.value});
}
- UploadFile() = 用于上传图片(这个不更新图片/状态)
const uploadFile = async (e) => {
console.log('Uploading file...');
const files = e.target.files;
const data = new FormData();
data.append('file', files[0]);
data.append('upload_preset', 'artemis');
const res = await fetch(`https://api.cloudinary.com/v1_1/${cludinaryAccount}/image/upload`, {
method: 'POST',
body: data
});
const file = await res.json();
console.log(file);
dispatch({
image: file.secure_url,
largeImage: file.eager[0].secure_url,
})
}
我无法使用 UploadFile() 更新图像的状态,不确定我做错了什么。下面是完整的完整代码。
import React, { useState, useReducer } from 'react';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import Router from 'next/router';
import Form from './styles/Form';
import formatMoney from '../lib/formatMoney';
import Error from './ErrorMessage';
const CREATE_LISTING_MUTATION = gql`
mutation CREATE_LISTING_MUTATION(
$title: String,
$description: String,
$address: String,
$availableFor: String,
$spaceType: String,
$height: String,
$accessType: String,
$security: String,
$features: String,
$nearbyStablishments: String,
$rules: String,
$image: String,
$largeImage: String,
$price: Int,
$bond: Int,
$minBookingStay: Int,
$size: String,
) {
createListing(
title: $title
description: $description
address: $address
availableFor: $availableFor
spaceType: $spaceType
height: $height
accessType: $accessType
security: $security
features: $features
nearbyStablishments: $nearbyStablishments
rules: $rules
image: $image
largeImage: $largeImage
price: $price
bond: $bond
minBookingStay: $minBookingStay
size: $size
) {
id
}
}
`;
const initialState = {
title: '',
description: '',
address: '',
availableFor: '',
spaceType: '',
height: '',
accessType: '',
security: '',
features: '',
nearbyStablishments: '',
rules: '',
image: '',
largeImage: '',
price: 0,
bond: 0,
minBookingStay: 0,
size: ''
};
function reducer(state, {field, value}) {
return {
...state,
[field]: value
}
}
export const CreateListing = () => {
const [state, dispatch] = useReducer(reducer,initialState);
const handleChange = async (e) => {
dispatch({field: e.target.name, value: e.target.value});
}
const {
title,
description,
address,
availableFor,
spaceType,
height,
accessType,
security,
features,
nearbyStablishments,
rules,
image,
largeImage,
price,
bond,
minBookingStay,
size
} = state;
const uploadFile = async (e) => {
console.log('Uploading file...');
const files = e.target.files;
const data = new FormData();
data.append('file', files[0]);
data.append('upload_preset', 'artemis');
const res = await fetch(`https://api.cloudinary.com/v1_1/${cludinaryAccount}/image/upload`, {
method: 'POST',
body: data
});
const file = await res.json();
console.log(file);
dispatch({
image: file.secure_url,
largeImage: file.eager[0].secure_url,
})
}
return (
<Mutation mutation={CREATE_LISTING_MUTATION} variables={state}>
{
/*
1. Expose createListing function
2. Expose the error and loading state
*/
}
{(createListing, {error, loading, called}) => {
// Possible params: error, loading, called, data, info
return (
<Form
data-test="form"
onSubmit={ async (e) => {
// Stop the form from submitting
e.preventDefault();
// Call the mutation
const res = await createListing();
// Change them to the single Listing page
console.log(res);
Router.push({
pathname: '/listing',
query: {
id: res.data.createListing.id
}
});
}}>
<h2>Lease my Space</h2>
<Error error={error}/>
{/* area-busy attribute is needed for our loading animation*/ }
<fieldset disabled={loading} aria-busy={loading}>
<label htmlFor="file">
Image
<input
type="file"
id = "file"
name = "file"
placeholder = "Upload an image"
required
onChange={uploadFile}
/>
{image && <img src={image} alt="Image Preview"/> }
</label>
<label htmlFor="title">
Title
<input
type="text"
id = "title"
name = "title"
placeholder = "title"
required
value = {title}
onChange={handleChange}
/>
</label>
<label htmlFor="description">
Description
<input
type="text"
id = "description"
name = "description"
placeholder = "Description"
required
value = {description}
onChange={handleChange}
/>
</label>
<label htmlFor="address">
Address
<input
type="text"
id = "address"
name = "address"
placeholder = "address"
required
value = {address}
onChange={handleChange}
/>
</label>
<label htmlFor="availableFor">
Available For
<input
type="text"
id = "availableFor"
name = "availableFor"
placeholder = "Available For"
required
value = {availableFor}
onChange={handleChange}
/>
</label>
<label htmlFor="spaceType">
Space Type
<input
type="text"
id = "spaceType"
name = "spaceType"
placeholder = "Space Type"
required
value = {spaceType}
onChange={handleChange}
/>
</label>
<label htmlFor="height">
Height
<input
type="text"
id = "height"
name = "height"
placeholder = "Height"
required
value = {height}
onChange={handleChange}
/>
</label>
<label htmlFor="accessType">
Access Type
<input
type="text"
id = "accessType"
name = "accessType"
placeholder = "Access Type"
required
value = {accessType}
onChange={handleChange}
/>
</label>
<label htmlFor="security">
Security
<input
type="text"
id = "security"
name = "security"
placeholder = "Security"
required
value = {security}
onChange={handleChange}
/>
</label>
<label htmlFor="features">
Features
<input
type="text"
id = "features"
name = "features"
placeholder = "Features"
required
value = {features}
onChange={handleChange}
/>
</label>
<label htmlFor="nearbyStablishments">
Nearby Stablishments
<input
type="text"
id = "nearbyStablishments"
name = "nearbyStablishments"
placeholder = "Nearby Stablishments"
required
value = {nearbyStablishments}
onChange={handleChange}
/>
</label>
<label htmlFor="rules">
Rules
<input
type="text"
id = "rules"
name = "rules"
placeholder = "Rules"
required
value = {rules}
onChange={handleChange}
/>
</label>
<label htmlFor="image">
Image
<input
type="text"
id = "image"
name = "image"
placeholder = "Image"
required
value = {image}
onChange={handleChange}
/>
</label>
<label htmlFor="largeImage">
Large Image
<input
type="text"
id = "largeImage"
name = "largeImage"
placeholder = "Large Image"
required
value = {largeImage}
onChange={handleChange}
/>
</label>
<label htmlFor="price">
Price
<input
type="number"
id = "price"
name = "price"
placeholder = "Price"
required
value = {price}
onChange={handleChange}
/>
</label>
<label htmlFor="bond">
Bond
<input
type="number"
id = "bond"
name = "bond"
placeholder = "Bond"
required
value = {bond}
onChange={handleChange}
/>
</label>
<label htmlFor="minBookingStay">
Min Booking stay
<input
type="number"
id = "minBookingStay"
name = "minBookingStay"
placeholder = "size"
required
value = {minBookingStay}
onChange={handleChange}
/>
</label>
<label htmlFor="size">
size
<input
type="text"
id = "size"
name = "size"
placeholder = "size"
required
value = {size}
onChange={handleChange}
/>
</label>
<button type="submit"> Submit</button>
</fieldset>
</Form>
)
}}
</Mutation>
)
}
export default CreateListing;
export {CREATE_LISTING_MUTATION};