开发者问题收集

react-native:如何在上下文 API 中更新状态?

2019-05-17
6430

当我在另一个组件中更新状态时,我无法在 ContextProvider.js 中重新渲染提供程序,因此消费者数据不会改变。

ContextProvider.js

export const AppContext = React.createContext({basketNumber:0});
export class ContextProvider extends React.PureComponent {
  state = {
      basketNumber:0,
  };

  render() {
    return (
      <AppContext.Provider value={this.state}>
        {this.props.children}
      </AppContext.Provider>
    );
  }
}

在另一个组件中我调用它:

import { AppContext } from './../../../components/ContextProvider';

export default class Example extends React.PureComponent  {
   static contextType = AppContext;
}

example 类中,我可以调用 basketNumber

this.context.basketNumber

但是我怎样才能更新它呢?

我试过这个:

this.context.basketNumber = 10;

//EDIT

我将此代码添加到 Context 提供程序:

addNumber(number) {
    this.setState({basketNumber:id});
};

并尝试在 example 类中调用它:

this.context.addNumber(10);

但是我收到此错误:

_this.context.addNumber is nut a function

2个回答

您可以在此处将其设置为功能组件:

const AppContext = React.createContext();
export const ContextProvider = ({ children }) => {
  const basketNumbers = [
    { number: 0 },
    { number: 1 }
  ]
  return (
    <AppContext.Provider value={basketNumbers}>
      {children}
    </AppContext.Provider>
  )
}

export default AppContext;

然后在另一个组件中像这样调用它:

import React, { useContext } from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
import AppContext from '../context/AppContext';

const IndexScreen = () => {
  const basketNumbers = useContext(AppContext);

  return (
    <View>
      <Text>Index Screen</Text>
      <FlatList data={basketNumbers} keyExtractor={(basketNumber) => basketNumber.number} renderItem={({ item }) => {
        return <Text>{item.number}</Text>
      }} />
    </View>
  )
};

const styles = StyleSheet.create({});

export default IndexScreen;

现在,如果您想编辑或更改数据,它将导致应用程序重新呈现,从而处理状态。

我所拥有的是传递静态列表并使用 Context api。

因此,您需要在 Provider 中初始化一段状态。

因此,您需要传递一个具有几个属性的对象,也许一个名为 data 的对象将包含您的 basketNumbers 数组。您的第二个属性可能是 addBasketNumber: () => { 。它是一个回调函数。

因此,如果我标记为 Index Screen 的第二个组件调用 addBasketNumber ,这将导致 Provider 随机生成一个新的 basketNumber 并将其添加到 basketNumbers 列表中。因此 basketNumbers 将重新渲染,整个应用程序将重新渲染,并且 Index Screen 将获得全新的 basketNumbers 列表。

因此,您需要对我转换为功能组件的第一个组件执行以下操作:

import React, { useState } from 'react';

const AppContext = React.createContext();
export const ContextProvider = ({ children }) => {
 const [basketNumbers, setBasketNumbers] = useState([]);

因此,默认情况下,您将拥有一个空数组,因为您将从没有篮子编号开始。现在 setBasketNumbers 是您的 setter,它完全替换了 basketNumbers 中的所有内容,但由于我已经提到过有一个回调函数,您可以添加一个辅助函数,如下所示:

import React, { useState } from 'react';

const AppContext = React.createContext();

export const ContextProvider = ({ children }) => {
  const [basketNumbers, setBasketNumbers] = useState([]);

  const addBasketNumber = () => {
    setBasketNumbers([...basketNumbers]);
  };

因此,此操作的目标是使用您的 setter 将新的篮子编号添加到您的 basketNumber 变量中。您使用该辅助函数所做的也是创建一个新数组,而不是更改 basketNumbers 的原始数组。因此,这个 [...basketNumbers] 只是意味着创建一个新数组,并在该新数组中获取我们拥有的所有当前篮子编号并将其添加到数组中。

然后,您需要为该 setBasketNumbers() 创建第二个参数,该参数将是一个对象,其新篮子编号的属性值将增加一。可能是 ${basketNumbers.length + 1 ?无论如何,您将希望将其传递到您的 Context 中,然后它应该在您的 FlatList 中重新呈现。

因此,类似这样的内容:

return (
    <AppContext.Provider value={{ data: basketNumbers, addBasketNumber }}>
      {children}
    </AppContext.Provider>
  )

因此,您似乎正在尝试使用或尝试使用上下文来管理状态。您不使用上下文来管理状态,而是使用它来移动数据。

我在这里使用 useState 调用来管理状态。上下文不能替代 Redux 等管理状态的功能。

Daniel
2019-09-12

更新上下文值。

查看此处 动态上下文

或者,您可以通过上下文向下传递一个函数来更新上下文。

查看此处 从嵌套组件更新上下文

Muhammad Mehar
2019-05-17