优雅的ES6方式在React中更新状态

时间:2017-06-10 20:19:51

标签: javascript reactjs react-native ecmascript-6

React中更新state的语法发生了很大变化。我试图找到最简单,最优雅的方式来启动和更新它。

得到这个RN代码:

const { quotes } = require('./quotes.json')

class QuoteScreen extends Component {
  state = {
    QuoteIndex: 0
  }
  render() {
    return (
      <Image ...>
        <View ...>
          ...
          <ButtonNextQuote
            onPress={() => {
              this.setState((prevState, props) => {
                return {
                  QuoteIndex: (prevState.QuoteIndex + 1) % (quotes.length - 1)
                }
              })
            }}
          />
        </View>
      </Image>
    )
  }
}

是否可以减少stateonPress的更新?

希望避免两次调用匿名函数,但不想引用和绑定处理程序。还想避免使用return ..

4 个答案:

答案 0 :(得分:8)

我会将更新函数存储在类外的变量中,例如

const newState = ({QuoteIndex: i}) => ({QuoteIndex: (i + 1) % nQuotes});

(当然你可以选择以你喜欢的任何方式定义这个功能,如果没有内联的话,“简洁”对你来说就不那么重要了)

然后你可以拨打this.setState(newState)

onPress={() => this.setState(newState)}

答案 1 :(得分:4)

这是我怎么做的。我在setState&#39; s回调(prevState)的第一个参数中使用了object destructuring,出于性能原因,我使用了一个单独的函数而不是匿名函数。另外,请注意我并不需要手动将函数绑定到this,因为我已经使用了箭头函数。

&#13;
&#13;
const { quotes } = require('./quotes.json')

class QuoteScreen extends Component {
  state = {
    QuoteIndex: 0
  }

  handleUpdateState = () => {
    this.setState(({ QuoteIndex }) => ({
      QuoteIndex: (QuoteIndex + 1) % (quotes.length - 1)
    }));
  }

  render() {
    return (
      <Image ...>
        <View ...>
          ...
          <ButtonNextQuote
            onPress={this.handleUpdateState}
          />
        </View>
      </Image>
    )
  }
}
&#13;
&#13;
&#13;

答案 2 :(得分:2)

我认为一种流行的好方法是

  1. 使用&#34;功能setState&#34;通过向this.setState提供回调来避免批量状态更新中的一些奇怪案例

  2. &#34;与组件类别分别声明状态更改&#34;这样可以重新使用和测试获得新状态的函数。

  3. 通过Dan Abramov的推文检查this article对这种方法的一个很好的解释

    示例:

    const { quotes } = require('./quotes.json')
    
    // keep pure function outside component to be reusable, testable
    const getQuoteIndex = ({ QuoteIndex }) => ({
      QuoteIndex: (QuoteIndex + 1) % (quotes.length - 1)
    })
    
    class QuoteScreen extends Component {
      state = {
        QuoteIndex: 0
      }
      // arrow function will take care of this binding
      handlePress = () => { this.setState(getQuoteIndex) }
      render() {
        return (
          <Image ...>
            <View ...>
              ...
              <ButtonNextQuote
                onPress={this.handlePress}
              />
            </View>
          </Image>
        )
      }
    }
    

答案 3 :(得分:1)

您希望每次render运行时都避免重新定义事件处理程序,就像其他人所说的那样。我更喜欢将对象传递给setState而不是回调函数:

_handlePress = () => {
  this.setState({
    QuoteIndex: (this.state.QuoteIndex + 1) % (quotes.length - 1)
  });
};

onPress={this._handlePress}

这更容易阅读,因为它明确了国家的来源。此外,您不必跟踪额外的回调函数。