Skip to content

Instantly share code, notes, and snippets.

@pioh
Created October 27, 2017 21:20
Show Gist options
  • Save pioh/59819d6fbb137c4b5a568b9b49cf390b to your computer and use it in GitHub Desktop.
Save pioh/59819d6fbb137c4b5a568b9b49cf390b to your computer and use it in GitHub Desktop.
RenderPropsExample
import * as React from 'react'
import {observer} from 'mobx-react'
import {FormGroup, Col, Label} from 'reactstrap'
import {OrderProvider} from 'components/OrderProvider/OrderProvider'
import {Input} from 'components/Input/Input'
import {Select} from 'components/Select/Select'
import {FieldFormat, InputAddon} from 'const/ReportForm/Field'
import {YesNoTable} from './YesNoTable'
import * as s from './Order.scss'
const yandexLink = ({address, lat, lon}) =>
`https://yandex.ru/maps/?ll=${lon}%2C${lat}&pt=${lon}%2C${lat}&text=${
encodeURIComponent(address)
}`
export const OrderFields = observer<{orderID: string}>(props =>
<OrderProvider id={props.orderID}>
{({order, isLoading, loadError, reload}) => (
isLoading ? <Loader /> :
loadError ? <ErrorBlock message={loadError.error} reload={reload} /> :
<FormGroup className={s.fields}>
<FormGroup>
<Label>
<Col sm={4}><span>Адрес</span></Col>
<Col sm={8}>
<Input disabled format={FieldFormat.TEXT} store={order} path='address' />
<a href={yandexLink(order)} target='_blank'>Яндекс карты</a>
</Col>
</Label>
</FormGroup>
<FormGroup>
<Label>
<Col sm={4}><span>Тип объекта</span></Col>
<Col sm={8}>
<Select store={order} path='objectType' options={{
disabled: true,
dictionary: [],
}} />
</Col>
</Label>
</FormGroup>
<FormGroup>
<Label>
<Col sm={4}><span>Предполагаемая цена</span></Col>
<Col sm={8}>
<Input
disabled
format={FieldFormat.PRICE}
store={order}
path='objectSalePrice'
addon={InputAddon.RUBLE}
/>
</Col>
</Label>
</FormGroup>
<FormGroup>
<Col><h5>Заказчик</h5></Col>
<Label>
<Col sm={4}><span>ФИО 1</span></Col>
<Col sm={8}>
<Input
disabled
format={FieldFormat.TEXT}
store={order}
path='customerName'
/>
</Col>
</Label>
<Label>
<Col sm={4}><span>Телефон 1</span></Col>
<Col sm={8}>
<Input
disabled
format={FieldFormat.PHONE}
store={order}
path='customerPhone'
/>
</Col>
</Label>
</FormGroup>
<FormGroup>
<Col>
<YesNoTable
title='Дополнительные данные'
disabled
fields={[{
store: order,
path: 'legalPersonOwner',
title: 'Собственником является юридическое лицо',
},{
store: order,
path: 'minorOwner',
title: 'Собственником является несовершеннолетнее лицо',
},{
store: order,
path: 'onerousTransaction',
title: 'Объект недвижимости был приобретен продавцом в период брака на основании возмездной сделки',
}]}
/>
</Col>
</FormGroup>
<FormGroup>
<Col><h5>Комментарий клиента</h5></Col>
<Col>
<Input
disabled
format={FieldFormat.TEXT}
store={order}
path='comment'
textarea
/>
</Col>
</FormGroup>
</FormGroup>
)}
</OrderProvider>
)
import * as React from 'react'
import {observable, action} from 'mobx'
import {observer} from 'mobx-react'
import {FileType} from 'const/FileType'
import {InspectionTime} from 'const/InspectionTime'
import {ApiEndpoint} from 'const/Api'
import {OrderStatus} from 'const/OrderStatus'
export interface IOrderProviderProps {
id: string|number,
children: (props: IChildrenProps) => any,
}
type IChildrenProps = OrderProvider['childrenProps']
const providers = new Map<string|number, [IChildrenProps,number]>()
export interface IOrderFile {
filePath: string|null,
created: string|null,
originalFilename: string|null,
size: number,
contentType: string|null,
fileType: FileType,
}
export const nullOrder = {
id: null as string|null,
address: null as string|null,
lat: null as number|null,
lon:null as number|null,
objectSalePrice: null as number|null,
customerName: null as string|null,
customerPhone: null as string|null,
legalPersonOwner: true,
minorOwner: false,
onerousTransaction: false,
crmId: null as number|string|null,
comment: null as string|null,
status: null as OrderStatus|null,
attachedFileList: [] as IOrderFile[],
inspectionDate: null as string|null,
inspectionTime: null as InspectionTime|null
}
export type IOrder = typeof nullOrder
@observer
class OrderProvider extends React.Component<IOrderProviderProps> {
@action reload = async () => {
this.childrenProps.isLoading = true
this.childrenProps.loadError = null
try {
let response = await fetch(`${ApiEndpoint}order/${this.props.id}`)
let order = await response.json()
if (order.error) return await this.receiveReloadError(order)
await this.receiveReloadOrder(order)
} catch (e) {
await this.receiveReloadError(e)
}
}
@action receiveReloadOrder = async (order: IChildrenProps['order']) => {
this.childrenProps.order = order
this.childrenProps.isLoading = false
this.childrenProps.loadError = null
}
@action receiveReloadError = async (e = {} as any) => {
if (!e.error) e.error = 'Что-то пошло не так'
this.childrenProps.isLoading = false
this.childrenProps.loadError = e
console.error(e.stack || e.message)
}
@observable childrenProps = {
isLoading: false,
loadError: null as null|{message:string, error: string},
order: nullOrder,
reload: this.reload,
}
componentWillMount () {
let provider = providers.get(this.props.id)
if (provider) {
provider[1]++
return
}
providers.set(this.props.id, [this.childrenProps,1])
this.reload()
}
componentWillUnmount () {
let provider = providers.get(this.props.id)
if (!provider) return
provider[1]--
if (provider[1] === 0) providers.delete(this.props.id)
}
render () {
let provider = providers.get(this.props.id)
if (provider) return this.props.children(provider[0])
return this.props.children(this.childrenProps)
}
}
export {OrderProvider}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment