【问题标题】:Elegant ES6 way to update state in React优雅的 ES6 方式在 React 中更新状态
【发布时间】:2017-11-12 15:30:37
【问题描述】:

在 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..

【问题讨论】:

    标签: javascript reactjs react-native ecmascript-6


    【解决方案1】:

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

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

    (当然你可以选择以任何你喜欢的方式定义函数,如果不内联,也许“简洁”对你来说不再那么重要了)

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

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

    【讨论】:

      【解决方案2】:

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

      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>
          )
        }
      }

      【讨论】:

      • 由于这个问题是用 ES6 标记的​​,因此可能值得指出您正在使用实验性功能(公共类字段)并简要说明启用它们需要做什么。
      • 对不起,我的错。基本上你有这个开箱即用的功能,最新版本的 babel 集成到 create-react-app 和 react-native 的依赖列表中。这是E6+,谢谢指出
      【解决方案3】:

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

      1. 通过向 this.setState 提供回调来使用“功能性 setState”,以避免批量状态更新中出现一些奇怪的情况

      2. “将状态变化与组件类分开声明”,以便获得新状态的函数可以单独重用和测试。

      查看this article,了解 Dan Abramov 的推文对这种方法的详细解释

      例子:

      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>
          )
        }
      }
      

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多