Sådan tvangsopfriskes en React-underordnet komponent: den nemme måde

Bemærk: Fra og med React 16 componentWillReceiveProps()er forældet, hvilket betyder, at hvis du bruger den version eller højere i dit projekt, er dette ikke et godt råd for dig.

I React-verdenen er det forkert at tvinge en re-render. Du bør lade DOM tage sig af sig selv, når React opfatter ændringer til stateeller props. For at følge disse mønstre er vi undertiden nødt til at gøre ting, der virker lidt fjollede. Overvej dette scenarie:

Vi har to komponenter - en forælder og et barn. Forældren foretager et API-opkald for at hente user. Fra dette, får vi ting som name, age, favorite color. Vi får også en idfra vores database. Vi videregiver det til vores underordnede komponent, som også vil foretage et API-opkald med bruger-id'et. Awesome - masser af data, der kommer ind i vores app.

Lad os sige, at vi gemmer en liste med sko i databasen. Når brugeren ændrer deres farvepræference, skriver serveren nye data til brugerens skoliste. Store! Bortset fra ser vi ikke den nye sko-liste i vores barnekomponent. Hvad giver?

Sidebemærkning : Selvfølgelig skal vi bare få skoene fra opkaldet til brugeren - dette er bare en forenklet forklaring.

Grundlæggende reaktion på gengivelse

Det korte er, at React kun opdaterer dele af DOM, der er ændret. I dette tilfælde har propsvi videregivet til skokomponenten ( userId) ikke ændret sig, så der ændres intet i vores underordnede komponent.

Farvepræferencen for brugeren opdateres, når vi får tilbage nye oplysninger fra API'en - forudsat at vi laver noget med svaret, når vi opdaterer en bruger.

Men da React ikke ser nogen grund til at opdatere skoelisten, gør det det ikke - selvom skoene på vores server nu er forskellige.

Startkoden

const UserShow extends Component { state = { user: {} } componentDidMount() { this.fetchUser().then(this.refreshUser) } setNewColor = color => { this.updateUser({color}).then(this.refreshUser) } refreshUser = res => this.setState({user: res.data.user}) render() { const { user } = this.state; return ( User name: {user.name} Pick color: {colors.map(color => this.setNewColor(color)} />)} )} ) } }

Vores ShoeListbliver bare en liste over sko, som vi henter fra serveren med brugerens id:

const ShoeList extends Component { state = { shoes: [] } componentDidMount() { this.fetchShoes(this.props.id) .then(this.refreshShoeList) } refreshShoeList = res => this.setState({ shoes: res.data.shoes }) render() { // some list of shoes } }

Hvis vi vil have sko-komponenten til at få fat i den nye liste over sko, skal vi opdatere de rekvisitter, vi sender til den. Ellers ser det ikke noget behov for at opdatere.

Faktisk ville den måde, som dette er skrevet på, ShoeListaldrig opdateres, da vi ikke er afhængige af rekvisitter til gengivelse. Lad os ordne det.

Udløs en underordnet komponent til at gengive igen

For at tvinge den underordnede komponent til at gengive igen - og foretage et nyt API-opkald - bliver vi nødt til at sende en prop, der vil ændre sig, hvis brugerens farvepræference er ændret.

For at gøre dette tilføjer vi en metode til setNewColor:

[...] setNewColor = color => { this.updateUser({color}).then(res => { this.refreshUser(res); this.refreshShoeList(); }) } refreshShoeList = () => this.setState({refreshShoeList: !this.state.refreshShoeList}) [...] 
    

This is a simple switch we can flip. I’ve kept things as simple as possible, but in production we’d want to make sure that the color we’re setting is different than the color we had before. Otherwise, there will be nothing to update.

Now in the ShoeList:

componentWillReceiveProps(props) { const { refresh, id } = this.props; if (props.refresh !== refresh) { this.fetchShoes(id) .then(this.refreshShoeList) } }

If you pass only refreshShoeList and then toggle based on that boolean, the component will just update forever and ever and ever.

We need to make sure the switch has flipped only once — so we’ll just check that the props coming in are different than the props we had before. If they are different, we’ll make a new API call to get the new list of shoes.

And boom — our child component has been “forced” to update.

componentWillReceiveProps

It’s worth taking just one more minute to review what’s going on in that last piece of code. In componentWillReceiveProps we have our only opportunity to view new props as they are coming in and compare them with previous props.

Here we can detect changes (like in refresh) and we can also make checks for new props (note, for instance, that refresh is initially undefined).

This React method is a very powerful way to manipulate and examine props.