简体   繁体   English

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

[英]react-native: How can I update state in context api?

When I update the state in another component, I can't re-render of the Provider in ContextProvider.js and hence the consumer data doesn't change.当我更新另一个组件中的状态时,我无法在ContextProvider.js重新渲染 Provider,因此消费者数据不会改变。

ContextProvider.js上下文提供者.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>
    );
  }
}

in another componet I call it:在另一个组件中,我称之为:

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

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

in example class, I can call basketNumberexample类中,我可以调用basketNumber

this.context.basketNumber

But how can I update it?但是我该如何更新呢?

I tried this:我试过这个:

this.context.basketNumber = 10;

//EDIT //编辑

I add this code to Context provider:我将此代码添加到上下文提供程序:

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

and try call it in example class:并尝试在example类中调用它:

this.context.addNumber(10);

But I get this error:但我收到此错误:

_this.context.addNumber is nut a function _this.context.addNumber 是一个函数

You can set it up as a functional component here:您可以在此处将其设置为功能组件:

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;

Then in the other component you call it like so:然后在另一个组件中你这样称呼它:

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;

Now if you want to edit or change the data it will cause the application to re render which is dealing with state.现在,如果您想编辑或更改数据,它将导致应用程序重新呈现正在处理状态的应用程序。

What I have is passing down a static list and using the Context api.我所拥有的是传递一个静态列表并使用 Context api。

So you would need to initialize a piece of state inside your Provider .因此,您需要在Provider初始化一段状态。

So you need to pass an object with a couple of properties, maybe one called data which will have your array of basketNumbers.因此,您需要传递一个具有几个属性的对象,也许一个称为data对象将包含您的篮子编号数组。 Your second property could be addBasketNumber: () => {} .您的第二个属性可能是addBasketNumber: () => {} It's a callback function.这是一个回调函数。

So if that second component that I labeled Index Screen ever calls addBasketNumber , that will cause the Provider to randomly generate a new basketNumber and add it to the list of basketNumbers.因此,如果我标记为 Index Screen 的第二个组件调用了addBasketNumber ,这将导致提供者随机生成一个新的篮子编号并将其添加到篮子编号列表中。 So the basketNumbers will re-render, the entire application will re-render and the Index screen will get the brand new list of basketNumbers.因此,basketNumbers 将重新呈现,整个应用程序将重新呈现,并且索引屏幕将获得全新的篮子编号列表。

So you want to do the following to the first component that I turned into a functional component:所以你想对我变成功能组件的第一个组件执行以下操作:

import React, { useState } from 'react';

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

So by default you are going to have an empty array because you are going to start off with no basket numbers.因此,默认情况下,您将拥有一个空数组,因为您将开始时没有篮子编号。 Now setBasketNumbers is your setter and completely replaces whatever is in basketNumbers but since I already did mention having a callback function, you can add a helper function like so:现在setBasketNumbers是你的 setter 并完全替换了basketNumbers任何内容,但因为我已经提到有一个回调函数,你可以像这样添加一个辅助函数:

import React, { useState } from 'react';

const AppContext = React.createContext();

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

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

So the goal of this is to use your setter to add in a new basket number to your basketNumber variable.因此,这样做的目的是使用您的 setter 将新的篮子编号添加到您的篮子编号变量中。 What you are also doing with that helper function is creating a new array and not changing the original array of basketNumbers .您还使用该辅助函数做的是创建一个新数组,而不是更改basketNumbers的原始数组。 So this [...basketNumbers] just means create a new array and inside of that new array take all the current basket numbers we have and add it to the array.所以这个[...basketNumbers]只是意味着创建一个新数组,在这个新数组中取出我们拥有的所有当前篮子编号并将其添加到数组中。

You then want to create a second argument to that setBasketNumbers() that would be an object with the property value of your new basket numbers being incremented by one.然后,您要为该setBasketNumbers()创建第二个参数,该参数将是一个对象,新篮子编号的属性值递增 1。 A ${basketNumbers.length + 1} maybe?一个${basketNumbers.length + 1}也许? Anyway, you will want to then pass that down into your Context and it should re render in your FlatList.无论如何,您将希望将其传递到您的上下文中,并且它应该在您的 FlatList 中重新呈现。

So something like this:所以像这样:

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

So it seems like what you are trying to do is using or trying to use context to manage state.因此,您似乎正在尝试使用或尝试使用上下文来管理状态。 You don't use context to manage state, you use it to move data around.您不使用上下文来管理状态,而是使用它来移动数据。

I am using useState calls to manage state here.我在这里使用useState调用来管理状态。 Context is not a replacement for managing state such as Redux. Context 不能替代 Redux 等管理状态。

To update context value.更新上下文值。

Checkout here Dynamic Context在这里结帐动态上下文

Or you can pass a function down through the context to update the context.或者您可以通过上下文向下传递函数以更新上下文。

Checout here Updating Context from a Nested Component在此处查看从嵌套组件更新上下文

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

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