我有一个相当大的视图组件来呈现一个表单,用户可以在其中添加注释,上传图像,在多个其他产品之间进行选择并提交。我将状态和功能保存在一个单独的组件中,并对该设置非常满意。
视图已大幅增长,我对应用程序的结构并不完全满意。
特别令我烦恼的是
props
和classes
变量传递给我使用的每个组件非常感谢有关如何更好地构建此代码的任何提示
import React from 'react';
import TextField from 'material-ui/TextField';
import Button from 'material-ui/Button';
import { MenuItem } from 'material-ui/Menu';
import { withStyles } from 'material-ui/styles';
import Chip from 'material-ui/Chip';
import Typography from 'material-ui/Typography';
import { CircularProgress } from 'material-ui/Progress';
import EntryImageView from "./entryImageView";
import {MarkedImage} from "./markedImage";
const styles = theme => ({
button: {
margin: theme.spacing.unit,
},
container: {
display: 'flex',
flexWrap: 'wrap',
},
menu: {
width: 200,
},
chipContainer: {
marginTop: theme.spacing.unit * 2,
display: 'flex',
flexWrap: 'wrap',
},
chip: {
margin: theme.spacing.unit / 2,
},
wrapper: {
marginTop: theme.spacing.unit*2
},
});
const ProductFormGroup = (props) => (
<div>
<TextField
id="selectedProduct"
required
select
label="Select a product"
error={props.selectProductError !== ''}
margin="normal"
fullWidth
value={(props.currentEntry.currentProduct === undefined || props.currentEntry.currentProduct === null) ? "" : props.currentEntry.currentProduct}
onChange={props.handleInputChange('currentProduct')}
SelectProps={{
MenuProps: {
className: props.menu,
},
name: "currentProduct"
}}
helperText={props.selectProductError || ""}
>
{props.job.selectedProducts.map((product, index) => (
<MenuItem key={index} value={product}>
{product.name}
</MenuItem>
))}
</TextField>
<TextField
margin="dense"
id="productQuantity"
label="Product Quantity"
fullWidth
name="productQuantity"
onChange={props.handleInputChange('productQuantity')}
value={props.productQuantity} />
<Button color="primary"
onClick={() => props.addSelectedChip()}
disabled={(props.productQuantity === '' || props.currentEntry.currentProduct === null)}>
add product
</Button>
</div>
);
const SelectedProductsGroup = (props) => (
<div>
<TextField
id="currentUpload"
select
label="Select an image to mark"
margin="normal"
fullWidth
value={props.currentUpload || ''}
onChange={props.handleInputChange('currentUpload')}
SelectProps={{
MenuProps: {
className: props.menu,
},
name: "currentUpload"
}}
>
{props.job.selectedUploads.map((file, index) => (
<MenuItem key={index} value={file}>
{file.name}
</MenuItem>
))}
</TextField>
{props.currentUpload &&
<Button color="primary" onClick={() => props.handleAttachmentDialogOpen(props.job.selectedUploads)}>
Edit marker on image
</Button>}
{props.selectedMarkedImage &&
<MarkedImage markerPosition={props.selectedMarkedImage.position}
attachment={props.selectedMarkedImage.attachment}
imageLoaded={props.markedImageLoaded}
handleImageLoaded={props.handleMarkedImageLoaded}
/>}
</div>
);
const SelectedProductsChipContainer = (props) => (
<div className={props.classes.wrapper}>
<Typography type="subheading" gutterBottom>
Selected Products
</Typography>
<div className={props.classes.chipContainer}>
{props.selectedProducts.map((product, index) => {
return (
<Chip
label={`${product.name} (${product.productQuantity})`}
key={index}
className={props.classes.chip}
onRequestDelete={() => props.handleRequestDeleteChip(product, "product")}
/>
)
})}
</div>
</div>
);
const SelectedImagesView = (props) => (
<div className={props.classes.wrapper}>
<Typography type="subheading" gutterBottom>
Selected images
</Typography>
<input type="file" id="myFile" onChange={props.handleFileUpload} />
{props.uploadLoading
? <CircularProgress/>
: null}
{props.selectedUploads.length > 0 && <EntryImageView selectedUploads={props.selectedUploads}
handleRequestDeleteChip={props.handleRequestDeleteChip} />}
</div>
);
const LocationDescriptionTextField = (props) => (
<TextField
id="locationDescription"
label="Location Description"
multiline
rows="4"
value={props.locationDescription}
onChange={props.handleInputChange('locationDescription')}
margin="normal"
fullWidth
/>
);
const CommentsTextField = (props) => (
<TextField
id="comments"
label="Comments"
multiline
rows="4"
value={props.comments}
onChange={props.handleInputChange('comments')}
margin="normal"
fullWidth
/>
);
export const CreateEntryForm = (props) => {
const { classes } = props;
return (
<div>
{props.job && <SelectedProductsGroup {...props} classes={classes}/>}
{props.selectedProducts.length > 0 && <SelectedProductsChipContainer {...props} classes={classes}/>}
{props.job && <ProductFormGroup {...props}/>}
<SelectedImagesView {...props} classes={classes} />
<LocationDescriptionTextField {...props} />
<CommentsTextField {...props} />
<Button color="primary" onClick={props.handleSubmit}>Create entry</Button>
</div>
)
};
export default withStyles(styles)(CreateEntryForm);