React intro
"Exotic" stateless functional component
function DemoComponent(props) {
console.log(props);
return React.createElement(
'div',
{ style: { background: 'navy', color: 'yellow' } },
'Hello world',
props.name
);
}
ReactDOM.render(
React.createElement(
DemoComponent,
{ name: 'Vasya' }
),
document.querySelector('#content')
);
statefull component
const r = React.createElement
class DemoComponent extends React.Component {
constructor() {
super(...arguments);
this.state = {
login: 'Vasya',
password: '',
showPassword: false
}
this.updateLogin = this.updateLogin.bind(this)
this.setShowPassword = e => this.setState({ showPassword: e.target.checked })
this.updatePassword = e => this.setState({ password: e.target.value })
}
updateLogin(e) {
// никогда не сохранять ссылку на этот объект события e
this.setState({ login: e.target.value });
}
render() {
return r(
'form', {},
r(
'label', {},
r(
'input', { type: 'text', placeholder: 'login',
value: this.state.login,
onChange: this.updateLogin
}
),
r(
'input', { type: this.state.showPassword ? 'text : ''password',
placeholder: 'password', value: this.state.password,
onChange: this.updatePassword
}
),
r(
'input', { type: 'checkbox',
value: this.state.showPassword,
onChange: this.setShowPassword
},
'Show password'
)
)
);
}
}
Pokedex
class DemoComponent extends React.Component {
constructor() {
super(...arguments);
this.state = {
pokemons: []
}
fetch('https://pokeapi.co/api/v1/pokemon/?limit=10')
.then(d => d.json())
.then(data => this.setState({ pokemons: data.objects }));
}
render() {
return r(
'ul',
{},
this.state.pokemons.map(p => r(
'li',
{ key: p.pkdx_id },
r('img', {src: `http://pokeapi.com/media/img/${p.pkdx_id}.png`})
))
);
}
}
перепишем на JSX
class Pokemon extends React.Component {
shouldComponentUpdate(newProps, newState) {
// this.props - предыдущее
// newProps - новое
// нужно ли перерисовывать true/false; по умолчанию true
if (newProps.pokemon == this.props.pokemon) return false;
}
render() {
const { pokemon, onDblClick } = this.props;
return (
<li>
<img src=`http://pokeapi.com/media/img/${pokemon.pkdx_id}.png`
onDblClick={() => onDblClick(pokemon)}
/>
${pokemon.name}
</li>
)
}
}
class DemoComponent extends React.Component {
constructor() {
super(...arguments);
this.state = {
pokemons: []
}
this.onPokemonRemove = pokemon => {
const newPokemons = this.state.pokemons.filter(p => p !== pokemon)
this.setState({ pokemons: newPokemons })
}
fetch('https://pokeapi.co/api/v1/pokemon/?limit=10')
.then(d => d.json())
.then(data => this.setState({ pokemons: data.objects }));
}
componentDidMount() {
const scrollbar = new GeminiScrollbar({element: this.refs.list})
scrollbar.create()
}
render() {
return (
<ul ref="list">
{ this.state.pokemons.map((p) => <Pokemon key={p.pkdc_id} pokemon={p}
onClick={this.onPokemonRemove}
/>)}
</ul>
);
}
}
ReactDOM.render(
<DemoComponent />,
document.querySelector('#content')
);
componentWillReceiveProps(nextProps) - единственный метод, в котором setState не вызовет render. Например для таблица рейтинга игроков (когда рейтинг меняется - рисовать стрелочки кто куда переместился)