简体   繁体   English

React Native:重新渲染组件,但道具没有改变

[英]React Native: Component rerender but props has not changed

I'm encountering this strange issue that I can figure out why is happing. 我遇到了一个奇怪的问题,可以弄清楚为什么要打apping。

观看问题

This should not be happening since the prop passed down to the History component has not been updated. 这应该不会发生,因为传递给“ History组件的道具尚未更新。

./components/History.js ./components/History.js

...
const History = ({ previousLevels }) => {
  return (
    <ScrollView style={styles.container}>
      {previousLevels.reverse().map(({ date, stressValue, tirednessValue }) => {
        return (
          <CardKBT
            key={date}
            date={date}
            stressValue={stressValue}
            tirednessValue={tirednessValue}
          />
        )
      })}
    </ScrollView>
  )
}
...
export default History

As can be seen in this code (below), the prop to the History is only updated once the user press Save. 如下面的代码所示,仅当用户按下保存后, History的道具才会更新。

App.js App.js

import React from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import { AppLoading, Font } from 'expo'
import Store from 'react-native-simple-store'
import { debounce } from 'lodash'

import CurrentLevels from './components/CurrentLevels'
import History from './components/History'

export default class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      isLoadingComplete: false,
      currentLevels: {
        stressValue: 1,
        tirednessValue: 1,
      },
      previousLevels: [],
    }

    this.debounceUpdateStressValue = debounce(this.onChangeStressValue, 50)
    this.debounceUpdateTirednessValue = debounce(
      this.onChangeTirednessValue,
      50
    )
  }

  async componentDidMount() {
    const previousLevels = await Store.get('previousLevels')
    if (previousLevels) {
      this.setState({ previousLevels })
    }
  }

  render() {
    const { stressValue, tirednessValue } = this.state.currentLevels

    if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
      return (
        <AppLoading
          ...
        />
      )
    } else {
      return (
        <View style={{ flex: 1 }}>
          <CurrentLevels
            stressValue={stressValue}
            onChangeStressValue={this.debounceUpdateStressValue}
            tirednessValue={tirednessValue}
            onChangeTirednessValue={this.debounceUpdateTirednessValue}
            onSave={this.onSave}
          />
          <History previousLevels={this.state.previousLevels} />
        </View>
      )
    }
  }

...

  onChangeStressValue = stressValue => {
    const { tirednessValue } = this.state.currentLevels
    this.setState({ currentLevels: { stressValue, tirednessValue } })
  }

  onChangeTirednessValue = tirednessValue => {
    const { stressValue } = this.state.currentLevels
    this.setState({ currentLevels: { stressValue, tirednessValue } })
  }

  onSave = () => {
    Store.push('previousLevels', {
      date: `${new Date()}`,
      ...this.state.currentLevels,
    }).then(() => {
      Store.get('previousLevels').then(previousLevels => {
        this.setState({
          currentLevels: { stressValue: 1, tirednessValue: 1 },
          previousLevels,
        })
      })
    })
  }
}

The component will re-render when one of the props or state changes, try using PureComponent or implement shouldComponentUpdate() and handle decide when to re-render. 当道具或状态之一发生更改时,组件将重新渲染,请尝试使用PureComponent或实现shouldComponentUpdate()并处理决定何时重新渲染。

Keep in mind, PureComponent does shallow object comparison, which means, if your props have nested object structure. 请记住, PureComponent浅对象比较,这意味着,如果您的道具具有嵌套的对象结构。 It won't work as expected. 它不会按预期工作。 So your component will re-render if the nested property changes. 因此,如果嵌套属性发生更改,您的组件将重新渲染。

In that case, you can have a normal Component and implement the shouldComponentUpdate() where you can tell React to re-render based on comparing the nested properties changes. 在那种情况下,您可以拥有一个普通的Component并实现shouldComponentUpdate() ,在此您可以告诉React根据比较嵌套属性的变化来重新渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM