Ustaw flagę jako state nadrzędnego kontenera i przekazuj ją (jak i funkcję ją modyfikującą) przez propsy. Nie trzeba żadnych kombinacji - wystarczy podstawowa funkcjonalność Reacta.
Przykład:
Kopiuj
// Container.js
import React from 'react';
import Item from './Item';
class Container extends React.Component {
constructor () {
this.state = {
isMouseDown: false,
}
this.toggleMouseDown = this.toggleMouseDown.bind(this)
}
toggleMouseDown() {
this.setState({isMouseDown: !this.state.isMouseDown})
}
render() {
return <div className="container">
{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((key) => (
<Item
key={key}
toggleMouseDown={this.toggleMouseDown}
isMouseDown={this.state.isMouseDown}
/>
))}
</div>
}
}
export default Container
Kopiuj
// Item.js
import React from 'react'
class Item extends React.Component {
constructor() {
this.state = {
selected: false,
}
this.select = this.select.bind(this)
this.selectIfMouseDown = this.selectIfMouseDown.bind(this)
}
select() {
this.setState({ selected: true })
}
selectIfMouseDown() {
if (this.props.isMouseDown) {
this.select()
}
}
render() {
return (
<div
className={`item ${this.state.selected ? 'selected' : ''}`}
onMouseDown={() => {
this.props.toggleMouseDown()
this.select()
}}
onMouseUp={this.props.toggleMouseDown}
onMouseEnter={this.selectIfMouseDown}
>
{this.props.isMouseDown ? 'down': 'up'}
</div>
)
}
}
export default Item
Live demo: https://stackblitz.com/edit/react-mousedown-1
Dla tych co proponują użycie globalnej flagi, jest to złe bo:
- Zaśmieca globalny namespace
- Jest ciężkie w debugowaniu
- Nie jest potrzebne
- Nie działa (a przynajmniej nie tak jak by się wydawało)
Ostatni punkt wymaga rozwinięcia:
React by przerenderować komponent musi wiedzieć, że zmiana zaszła. React nie nasłuchuje wszelkich zmian w kontekście JS, funkcję render()
komponentu trigeruje tylko zmiana stanu przez setState
i zmiana propsów.
Od biedy da się zrobić takim hackiem proste rzeczy, ale nie da się synchronizować stanu pomiędzy komponentami. Poniższy przykład "działa", ale tylko dlatego, że oprócz zmiany zmiennej globalnej jest także zmieniany stan komponentu this.setState({ selected: true })
- zauważ, że pozostałe komponenty "nie widzą" stanu myszy, dopóki na nie nie najedzie (w ogóle cyrk się robi jak dłużej poklikasz - mysz Schrodingera, nie wiesz czy wciśnięta czy nie póki nie spojrzysz na nią):
https://stackblitz.com/edit/react-mousedown-2
PS
@cerrato Miałeś dobre przeczucie, po prostu musiałeś troszkę poczekać aż ktoś to zjedzie :P
Freja Draco