рдЖрдЬ рд╣рдо рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рд╕реНрд╡рдЪреНрдЫ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдкрд░ рд╕рд╛рдордЧреНрд░реА рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдХреБрдЫ рдФрд░ рдЙрдкрдпреЛрдЧреА рд╕реБрдЭрд╛рд╡ рджрд┐рдП рдЧрдП рд╣реИрдВред

тЖТ
рдкрд╣рд▓рд╛ рднрд╛рдЧ рдкрдврд╝реЗрдВ8. рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рддрддреНрд╡реЛрдВ рдХреЛ рдШрдЯрдХреЛрдВ рдореЗрдВ рдмрджрд▓реЗрдВ
рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рддрддреНрд╡реЛрдВ рдХреЛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдШрдЯрдХреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЛ рдРрд╕реЗ рддрддреНрд╡реЛрдВ рдХрд╛ "рдШрдЯрдХрдХрд░рдг" рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдкреНрд░рддреНрдпреЗрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рдЕрдкрдиреЗ рдХрд╛рд░рдг рд╣реИрдВ рдХрд┐ рд╡рд╣ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд░рд┐рдПрдХреНрдЯ рдХреЛрдб рдХреНрдпреЛрдВ рд▓рд┐рдЦрддрд╛ рд╣реИред рдпрд╣ рдПрдХ рдЬрд╛рдирдмреВрдЭрдХрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдпрд╛ рдпрд╣ рдПрдХ рджреБрд░реНрдШрдЯрдирд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдЖрд╡реЗрджрди рдореЗрдВ рд╕рдорд╛рди рдХреЛрдб рдЕрдВрд╢реЛрдВ рдХреЗ рдкреНрд░рдХрдЯ рд╣реЛрдиреЗ рдХрд╛ рдХрд╛рд░рдг рдЬреЛ рднреА рд╣реЛ, рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рдпрд╣ рд╕реЛрдЪрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╕реНрдерд┐рддрд┐ рдХреЛ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░реЗрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдХрд┐рд╕реА рдиреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреА рдЖрджрдд рдирд╣реАрдВ рдмрдирд╛рдИ рд╣реИ, рддреЛ рд╡реЗ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдмрд╛рд░-рдмрд╛рд░ рдЙрддреНрдкрдиреНрди рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЯреАрдо рдХрд╛ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреМрди рд╕рд╛ рд╣реИ? рдпрд╣ рдмрд╕ рдЕрдкрдиреЗ рд╕рд╣рдпреЛрдЧрд┐рдпреЛрдВ рдХреЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЬреАрд╡рди рдХреЛ рдЬрдЯрд┐рд▓ рдмрдирд╛рддрд╛ рд╣реИ, рдЬреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛрдб рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдиреЗ рдкрд░ рднреНрд░рдорд┐рдд рд╣реЛ рдЬрд╛рдПрдВрдЧреЗред рдпрджрд┐ рдЙрдиреНрд╣реЗрдВ рд╕рдорд╛рди рдХреЛрдб рдЕрдВрд╢реЛрдВ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╣реИ рддреЛ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ "рдЙрдкрд╣рд╛рд░" рдорд┐рд▓реЗрдЧрд╛ред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ рдФрд░ рд╕реЛрдЪреЗрдВ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░реЗрдВ:
const SomeComponent = () => ( <Body noBottom> <Header center>Title</Header> <Divider /> <Background grey> <Section height={500}> <Grid spacing={16} container> <Grid xs={12} sm={6} item> <div className={classes.groupsHeader}> <Header center>Groups</Header> </div> </Grid> <Grid xs={12} sm={6} item> <div> <img src={photos.groups} alt="" className={classes.img} /> </div> </Grid> </Grid> </Section> </Background> <div> <Section height={500}> <Grid spacing={16} container> <Grid xs={12} sm={6} item> <div className={classes.labsHeader}> <Header center>Labs</Header> </div> </Grid> <Grid xs={12} sm={6} item> <div> <img src={photos.labs} alt="" className={classes.img} /> </div> </Grid> </Grid> </Section> </div> </Body> )
рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдм
xs={12} sm={6}
рд╕реЗ
xs={12} sm={4}
рд╕реЗ рдЧреНрд░рд┐рдб рдкреИрд░рд╛рдореАрдЯрд░ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдХрд╛рд░реНрдп рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реБрдЦрдж рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЪрд╛рд░ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдХреЛрдб рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдШрдЯрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рд╕реБрдВрджрд░рддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рдЙрдкрд░реЛрдХреНрдд рдХреЗ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рдХреЛрдб рдмрджрд▓ рд░рд╣рд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдкрд░рд┐рд╡рд░реНрддрди рд╣рд░ рдЬрдЧрд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ рдЬрд╣рд╛рдБ рдЧреНрд░рд┐рдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
const SomeComponent = ({ classes, xs = 12, sm = 6, md, lg }) => { const BodySection = ({ header, src }) => { const gridSizes = { xs, sm, md, lg } return ( <Section height={500}> <Grid spacing={16} container> <Grid {...gridSizes} item> <div className={classes.groupsHeader}> <Header center>{header}</Header> </div> </Grid> <Grid {...gridSizes} item> <div> <img src={src} alt="" className={classes.img} /> </div> </Grid> </Grid> </Section> ) } return ( <Body noBottom> <Header center>Title</Header> <Divider /> <Background grey> <BodySection header="Groups" src={photos.groups} /> </Background> <div> <BodySection header="Labs" src={photos.labs} /> </div> </Body> ) }
рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдпрд╣рд╛рдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдиреНрдпреВрдирддрдо рд░реВрдкрд╛рдВрддрд░рдг рдХреЛрдб рднреА рдЗрд╕ рдХреЛрдб рдХреЛ рдЙрд╕рдХреЗ рдкрдврд╝рдиреЗ рдФрд░ рд╕рдорд░реНрдерди рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рддрд╛ рд╣реИред рд╡рд╣, рдЙрд╕реА рд╕рдордп, рдЙрд╕реЗ рд╕реМрдВрдкреЗ рдЧрдП рдХрд╛рд░реНрдп рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рддрд░реАрдХрд╛ рд╣реИред
9. рдЕрдкрдиреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рдмрд┐рдХреНрд░реА рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рдореБрдЭреЗ рдХрднреА-рдХрднреА рдШрдЯрдХ рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рдереА, рд▓реЗрдХрд┐рди рдЙрди рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рдирдореЗрдВ рдШрдЯрдХ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ рдПрдХ рдШрдЯрдХ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдЬреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рдЬрдЯрд┐рд▓ рд╣реИред рдпрд╣
ConfirmAvailability.js
рджреНрд╡рд╛рд░рд╛
ConfirmAvailability.js
:
import React from 'react' import Grid from '@material-ui/core/Grid' import Typography from '@material-ui/core/Typography' import MenuItem from '@material-ui/core/MenuItem' import Select from '@material-ui/core/Select' import Time from 'util/time' export default class TimeZonePicker extends React.Component { state = { time: new Date(), offset: -(new Date().getTimezoneOffset() / 60), } componentDidMount() { this.props.setOffset(this.state.offset) } handleChange = (event) => { const d = new Date() d.setTime( d.getTime() + d.getTimezoneOffset() * 60 * 1000 + event.target.value * 3600 * 1000, ) this.setState({ time: d, offset: event.target.value, }) this.props.setOffset(event.target.value) } render() { const timezones = [] for (let i = -12; i <= 14; i++) { timezones.push( <MenuItem key={i} value={i}> {i > 0 ? '+' : null} {i} </MenuItem>, ) } return ( <React.Fragment> <Grid container justify="space-between"> <div> <Typography>Current time</Typography> <Typography variant="h6" gutterBottom> {Time.formatTime(this.state.time)} </Typography> </div> <div> <Typography>Set timezone</Typography> <Select value={this.state.offset} onChange={this.handleChange}> {timezones} </Select> </div> </Grid> </React.Fragment> ) } }
рдЗрд╕ рдШрдЯрдХ рдХреА рдХрд▓реНрдкрдирд╛ рдПрдХ рд╕рд░рд▓ рддрдВрддреНрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХреА рдЧрдИ рдереА, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдЕрддреНрдпрдзрд┐рдХ рд╕рдВрдмрдВрдзрд┐рдд рддрд░реНрдХ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдХрдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЬрд┐рд╕ рд╕рдордп рдпрд╣ рдХреЛрдб рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рд░рд┐рдПрдХреНрдЯ рд╣реБрдХ рдЕрднреА рддрдХ рдЬрд╛рд░реА рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рдереЗ, рд▓реЗрдХрд┐рди рд░рд┐рдПрдХреНрдЯ рдореЗрдВ рдЙрдЪреНрдЪ-рдХреНрд░рдо рдХреЗ рдШрдЯрдХ рдФрд░ рд░реЗрдВрдбрд░ рд╕реНрдЯреНрд░рд┐рдкреНрд╕ рдЬреИрд╕реА рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпрд╛рдВ рд╢рд╛рдорд┐рд▓ рдереАрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдШрдЯрдХ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╣рдореЗрдВ рдореМрдЬреВрджрд╛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд┐рдирд╛ рдШрдЯрдХреЛрдВ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред
рдкрд╣рд▓реЗ, рд╕рднреА рдХреЛрдб рдПрдХ рд╣реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЧрдП рдереЗред рдЕрдм рд╣рдо рдЗрд╕реЗ рджреЛ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдкрд╣рд▓реА рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рд╣реИ -
SelectTimeZone.js
:
import React from 'react' class SelectTimeZone extends React.Component { state = { time: new Date(), offset: -(new Date().getTimezoneOffset() / 60), } componentDidMount() { this.props.setOffset(this.state.offset) } handleChange = (event) => { const d = new Date() d.setTime( d.getTime() + d.getTimezoneOffset() * 60 * 1000 + event.target.value * 3600 * 1000, ) this.setState({ time: d, offset: event.target.value, }) this.props.setOffset(event.target.value) } getTimeZones = () => { const timezones = [] for (let i = -12; i <= 14; i++) { timezones.push( <MenuItem key={i} value={i}> {i > 0 ? '+' : null} {i} </MenuItem>, ) } return timezones } render() { return this.props.render({ ...this.state, getTimeZones: this.getTimeZones, }) } }
рдпрд╣рд╛рдБ рджреВрд╕рд░реА рдлрд╝рд╛рдЗрд▓ рдХреИрд╕реА рджрд┐рдЦрддреА рд╣реИ -
TimeZonePicker.js
:
import React from 'react' import Grid from '@material-ui/core/Grid' import Typography from '@material-ui/core/Typography' import MenuItem from '@material-ui/core/MenuItem' import Select from '@material-ui/core/Select' import Time from 'util/time' const TimeZonePicker = () => ( <SelectTimeZone render={({ time, offset, getTimeZones, handleChange }) => ( <Grid container justify="space-between"> <div> <Typography>Current time</Typography> <Typography variant="h6" gutterBottom> {Time.formatTime(time)} </Typography> </div> <div> <Typography>Set timezone</Typography> <Select value={offset} onChange={handleChange}> {getTimeZones()} </Select> </div> </Grid> )} /> ) export default TimeZonePicker
рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд╛рдж, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рдкрд╣рд▓реЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рд╛рдл рд╣реЛ рдЧрдпрд╛ред рд╣рдордиреЗ рдШрдЯрдХ рдХреЗ рдкреНрд░рд╕реНрддреБрддрд┐ рднрд╛рдЧ рд╕реЗ рддрд░реНрдХ рдХреЛ рдирд┐рдХрд╛рд▓рд╛ред рдЕрдм, рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдмрд╣реБрдд рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
10. рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЖрдкрдХреЛ рдЬрд┐рддрдиреЗ рдЕрдзрд┐рдХ рд░рд╛рдЬреНрдп рдХреЗ рдЯреБрдХрдбрд╝реЗ рдХрд░рдиреЗ рд╣реЛрдВрдЧреЗ, рдЙрддрдиреЗ рд╣реА рдЬрдЯрд┐рд▓ рдЙрдкрдпреЛрдЧ рдХреА
useState
ред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:
import React from 'react' import axios from 'axios' const useFrogs = () => { const [fetching, setFetching] = React.useState(false) const [fetched, setFetched] = React.useState(false) const [fetchError, setFetchError] = React.useState(null) const [timedOut, setTimedOut] = React.useState(false) const [frogs, setFrogs] = React.useState(null) const [params, setParams] = React.useState({ limit: 50 }) const timedOutRef = React.useRef() function updateParams(newParams) { if (newParams != undefined) { setParams(newParams) } else { console.warn( 'You tried to update state.params but the parameters were null or undefined', ) } } function formatFrogs(newFrogs) { const formattedFrogs = newFrogs.reduce((acc, frog) => { const { name, age, size, children } = frog if (!(name in acc)) { acc[name] = { age, size, children: children.map((child) => ({ name: child.name, age: child.age, size: child.size, })), } } return acc }, {}) return formattedFrogs } function addFrog(name, frog) { const nextFrogs = { ...frogs, [name]: frog, } setFrogs(nextFrogs) } function removeFrog(name) { const nextFrogs = { ...frogs } if (name in nextFrogs) delete nextFrogs[name] setFrogs(nextFrogs) } React.useEffect(() => { if (frogs === null) { if (timedOutRef.current) clearTimeout(timedOutRef.current) setFetching(true) timedOutRef.current = setTimeout(() => { setTimedOut(true) }, 20000) axios .get('https://somefrogsaspi.com/api/v1/frogs_list/', { params }) .then((response) => { if (timedOutRef.current) clearTimeout(timedOutRef.current) setFetching(false) setFetched(true) if (timedOut) setTimedOut(false) if (fetchError) setFetchError(null) setFrogs(formatFrogs(response.data)) }) .catch((error) => { if (timedOutRef.current) clearTimeout(timedOutRef.current) console.error(error) setFetching(false) if (timedOut) setTimedOut(false) setFetchError(error) }) } }, []) return { fetching, fetched, fetchError, timedOut, frogs, params, addFrog, removeFrog, } } export default useFrogs
рдпрджрд┐ рдЖрдк рдЗрд╕ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдпрджрд┐ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ
useReducer
:
import React from 'react' import axios from 'axios' const initialFetchState = { fetching: false fetched: false fetchError: null timedOut: false } const initialState = { ...initialFetchState, frogs: null params: { limit: 50 } } const reducer = (state, action) => { switch (action.type) { case 'fetching': return { ...state, ...initialFetchState, fetching: true } case 'fetched': return { ...state, ...initialFetchState, fetched: true, frogs: action.frogs } case 'fetch-error': return { ...state, ...initialFetchState, fetchError: action.error } case 'set-timed-out': return { ...state, ...initialFetchState, timedOut: true } case 'set-frogs': return { ...state, ...initialFetchState, fetched: true, frogs: action.frogs } case 'add-frog': return { ...state, frogs: { ...state.frogs, [action.name]: action.frog }} case 'remove-frog': { const nextFrogs = { ...state.frogs } if (action.name in nextFrogs) delete nextFrogs[action.name] return { ...state, frogs: nextFrogs } } case 'set-params': return { ...state, params: { ...state.params, ...action.params } } default: return state } } const useFrogs = () => { const [state, dispatch] = React.useReducer(reducer, initialState) const timedOutRef = React.useRef() function updateParams(params) { if (newParams != undefined) { dispatch({ type: 'set-params', params }) } else { console.warn( 'You tried to update state.params but the parameters were null or undefined', ) } } function formatFrogs(newFrogs) { const formattedFrogs = newFrogs.reduce((acc, frog) => { const { name, age, size, children } = frog if (!(name in acc)) { acc[name] = { age, size, children: children.map((child) => ({ name: child.name, age: child.age, size: child.size, })), } } return acc }, {}) return formattedFrogs } function addFrog(name, frog) { dispatch({ type: 'add-frog', name, frog }) } function removeFrog(name) { dispatch({ type: 'remove-frog', name }) } React.useEffect(() => { if (frogs === null) { if (timedOutRef.current) clearTimeout(timedOutRef.current) timedOutRef.current = setTimeout(() => { setTimedOut(true) }, 20000) axios .get('https://somefrogsaspi.com/api/v1/frogs_list/', { params }) .then((response) => { if (timedOutRef.current) clearTimeout(timedOutRef.current) const frogs = formatFrogs(response.data) dispatch({ type: 'set-frogs', frogs }) }) .catch((error) => { if (timedOutRef.current) clearTimeout(timedOutRef.current) console.error(error) dispatch({ type: 'fetch-error', error }) }) } }, []) return { fetching, fetched, fetchError, timedOut, frogs, params, addFrog, removeFrog, } } export default useFrogs
рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг
useState
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╢рд╛рдпрдж рдХреНрд▓реАрдирд░ рдирд╣реАрдВ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдХреЛрдб рдХреЛ рджреЗрдЦрдХрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдирдпрд╛ рдХреЛрдб рдмрдирд╛рдП рд░рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реИред рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЬрдм
useReducer
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛
useReducer
рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рд╣реБрдХ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ рд░рд╛рдЬреНрдп рдХреЗ рдЕрдкрдбреЗрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпреЗ рд╕рднреА рдСрдкрд░реЗрд╢рди
useReducer
рдЕрдВрджрд░ рдПрдХ рд╕реНрдерд╛рди рдкрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реЛрддреЗ рд╣реИрдВред
рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рддрд░реНрдХ рд▓рд┐рдЦрдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдореЗрдВ рд╣реБрдХ рдХреЗ рдЕрдВрджрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдХрд┐ рд░рд╛рдЬреНрдп рдХрд╛ рдЕрдЧрд▓рд╛ рд╣рд┐рд╕реНрд╕рд╛ рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ
useReducer
, рдЖрдкрдХреЛ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╕рдм рдХреБрдЫ
reducer
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЖрддрд╛ рд╣реИред рд╣рдореЗрдВ рдмрд╕ рдЙрдкрдпреБрдХреНрдд рдкреНрд░рдХрд╛рд░ рдХреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИред
11. рд╡рд┐рд╡рд╛рджрд╛рд╕реНрдкрдж рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдШреЛрд╖рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдЗрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдПрдХ
useEffect
рд╕рдлрд╛рдИ
useEffect
:
React.useEffect(() => { setMounted(true) return () => { setMounted(false) } }, [])
рдПрдХ рдЕрдиреБрднрд╡реА рд░рд┐рдПрдХреНрдЯрд░ рдбреЗрд╡рд▓рдкрд░ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рд▓реМрдЯреЗ рдлрд╝рдВрдХреНрд╢рди рдХреА рднреВрдорд┐рдХрд╛ рдХреНрдпрд╛ рд╣реИ, рд╡рд╣ рдЖрд╕рд╛рдиреА рд╕реЗ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рдордЭ рдЬрд╛рдПрдЧрд╛ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдХрд▓реНрдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдЬреЛ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИ, рддреЛ рдЗрд╕ рдХреЛрдб рдХреЛ рдкрдврд╝реЗрдЧрд╛, рдХреЛрдб рдореЗрдВ рдЕрдкрдиреЗ рдЗрд░рд╛рджреЛрдВ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛ред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдШреЛрд╖рдгрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рд╕рд╛рд░реНрдердХ рдирд╛рдо рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдХреЛрдб рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
React.useEffect(() => { setMounted(true) return function cleanup() { setMounted(false) } }, [])
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдХреНрдпрд╛ рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИред
12. Prettier рдХрд╛ рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ
Prettier рд╡реНрдпрдХреНрддрд┐рдЧрдд рдбреЗрд╡рд▓рдкрд░реНрд╕ рдФрд░ рдЯреАрдореЛрдВ рдХреЛ рдХреЛрдб рд╕реНрд╡рд░реВрдкрдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╕рдВрдЧрдд рдФрд░ рд╕реБрд╕рдВрдЧрдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрдирд╛рдП рд░рдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЙрдкрдХрд░рдг рд╕рдордп рдФрд░ рдкреНрд░рдпрд╛рд╕ рдХреЛ рдмрдЪрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреА рд╢реИрд▓реА рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░рдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдХрдо рдХрд░рдХреЗ рдХреЛрдб рд╕рдореАрдХреНрд╖рд╛ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИред рдкреНрд░рд┐рдЯрд┐рдпрд░ рд╕реНрд╡рдЪреНрдЫ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд▓реЗрдЦрди рддрдХрдиреАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдЧреНрд░рд╛рдорд░реЛрдВ рдХреЛ рднреА рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдЙрдкрдХрд░рдг рджреНрд╡рд╛рд░рд╛ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП рдирд┐рдпрдо рд╕рдВрдкрд╛рджрди рдпреЛрдЧреНрдп рд╣реИрдВред рдирддреАрдЬрддрди, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╣рд░ рдХреЛрдИ рдЗрд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕рд╛ рдХрд┐ рд╡реЗ рдлрд┐рдЯ рджреЗрдЦрддреЗ рд╣реИрдВред
13. рдЯреБрдХрдбрд╝рд╛ рдШреЛрд╖рдгрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЖрд╢реБрд▓рд┐рдкрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдареЛрд░
рдЗрд╕ рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд╛ рд╕рд╛рд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЛ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдЦрдВрдб рдШреЛрд╖рдгрд╛ рдХрд╛ рдЫреЛрдЯрд╛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:
const App = () => ( <> <FrogsTable /> <FrogsGallery /> </> )
рдпрд╣рд╛рдБ рдкреВрд░реНрдг рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:
const App = () => ( <React.Fragment> <FrogsTable /> <FrogsGallery /> </React.Fragment> )
14. рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╕рдордп рддрддреНрд╡реЛрдВ рдХреА рдирд┐рдпреБрдХреНрддрд┐ рдХреЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдХреНрд░рдо рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВред
рдЬрдм рдореИрдВ рдХреЛрдб рд▓рд┐рдЦрддрд╛ рд╣реВрдВ, рддреЛ рдореИрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдХреНрд░рдо рдореЗрдВ рдХреБрдЫ рдХрдорд╛рдВрдб рдХреА рд╡реНрдпрд╡рд╕реНрдерд╛ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рдлрд╝рд╛рдЗрд▓реЗрдВ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╕рдордп рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ (рдпрд╣рд╛рдВ рдЕрдкрд╡рд╛рдж рдХреЗрд╡рд▓ рдЖрдпрд╛рдд
react
):
import React from 'react' import { useSelector } from 'react-redux' import styled from 'styled-components' import FrogsGallery from './FrogsGallery' import FrogsTable from './FrogsTable' import Stations from './Stations' import * as errorHelpers from '../utils/errorHelpers' import * as utils from '../utils/'
рдЗрд╕ рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдХреЛрдИ рд╕реЛрдЪ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдЖрджреЗрд╢ рдирд╣реАрдВ рджреЗрдЦрд╛ рдЧрдпрд╛ рд╣реИред рдЖрдЦрд┐рд░рдХрд╛рд░, рдЖрдпрд╛рддрд┐рдд рдЗрдХрд╛рдЗрдпрд╛рдВ рднреА рд╡рд░реНрдгрд╛рдиреБрдХреНрд░рдо рдореЗрдВ рдХреНрд░рдордмрджреНрдз рдирд╣реАрдВ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреЗ рдХреНрд░рдо рдореЗрдВ рдХреБрдЫ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдирд╛ рдХреЗрд╡рд▓ рдЖрджреЗрд╢ рджреЗрдиреЗ рд╡рд╛рд▓реА рдпреЛрдЬрдирд╛ рдХрд╛ рдПрдХ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдореИрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред
рдореИрдВ, рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдХреЛрдб рдХреА рд╢реБрджреНрдзрддрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рдпрдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдЬреЛ рд╡реЗ рдЕрдиреБрд╕рд░рдг рдХрд┐рдП рдЧрдП рдХреНрд░рдо рдореЗрдВ рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ:
- рдЖрдпрд╛рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ред
- рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдЖрдпрд╛рдд рдХрд░реЗрдВ (рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреНрд░рдо рдореЗрдВ)ред
- рдХрд┐рд╕реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдкреВрд░реНрдг рдЖрдЬреНрдЮрд╛ (рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреЗ рдХреНрд░рдо рдореЗрдВ)ред
- рд╕рд╛рдкреЗрдХреНрд╖ рдЖрдпрд╛рдд рдЖрджреЗрд╢ (рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреНрд░рдо рдореЗрдВ)ред
- рдкреНрд░рдкрддреНрд░
import * as
ред - рдкреНрд░рдкрддреНрд░
import './<some file>.<some ext>'
рдЖрджреЗрд╢ import './<some file>.<some ext>'
ред
рдФрд░ рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдХреИрд╕реЗ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЪрд░ред рдХрд╣реЗрдВ - рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдЧреБрдг:
const character = (function() { return { cry() {
рдпрджрд┐ рдЖрдк рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╕рдордп рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЖрджреЗрд╢ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирд┐рдпрдореЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ - рддреЛ рдЗрд╕рдХрд╛ рд╢реБрджреНрдзрддрд╛ рдкрд░ рд▓рд╛рднрдХрд╛рд░реА рдкреНрд░рднрд╛рд╡ рдкрдбрд╝реЗрдЧрд╛ред
рдкрд░рд┐рдгрд╛рдо
рд╣рдордиреЗ рдЖрдкрдХреЛ рд╕реНрд╡рдЪреНрдЫ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдпреБрдХреНрддрд┐рдпрд╛рдВ рдкреНрд░рджрд╛рди рдХреА рд╣реИрдВред рд╣рдо рдЖрд╢рд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдЙрдирдХреЗ рдмреАрдЪ рдХреБрдЫ рдРрд╕рд╛ рдкрд╛рдПрдВрдЧреЗ рдЬреЛ рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИред
рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ! рдЗрд╕ рдЖрд▓реЗрдЦ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рд╕реБрдЭрд╛рд╡реЛрдВ рдореЗрдВ рдЖрдк рдХреНрдпрд╛ рд╕рд┐рдлрд╛рд░рд┐рд╢реЗрдВ рдЬреЛрдбрд╝реЗрдВрдЧреЗ?
