简体   繁体   English

React Native 防止上下文依赖重新渲染所有组件

[英]React Native Prevent Context Dependency Rerender All Components

I have three buttons.我有三个按钮。 When I click one button, it fires Context's memo function to add an item into Context's items.当我单击一个按钮时,它会触发 Context 的备忘录 function 以将项目添加到 Context 的项目中。 I see that clicking one button re-renders all the three buttons, which is not expected.我看到单击一个按钮会重新呈现所有三个按钮,这是意料之中的。 I need to re-render only the clicked button.我只需要重新渲染单击的按钮。 Please advice.请指教。

CounterContext.js CounterContext.js

import { createContext } from "react";

export const CounterContext = createContext(null);

App.js应用程序.js

import React from "react";
import { Text, StyleSheet } from "react-native";
import MyButton from "./MyButton";
import { CounterContext } from "./CounterContext";

function counterReducer(prevState, action) {
  switch (action.type) {
    case "ADD_ITEM":
      let items = [...prevState.items, action.item];

      return {
        items: items,
        count: items.length
      };
    default:
      console.log("No action type");
      break;
  }
}
const buttons = ["1", "2", "3"];

export default function App() {
  const [counterState, counterDispatch] = React.useReducer(counterReducer, {
    items: [],
    count: 0
  });

  const counterContext = React.useMemo(
    () => ({
      addItem: item => {
        counterDispatch({
          type: "ADD_ITEM",
          item: item
        });
      },
      items: counterState.items,
      itemsCount: counterState.items.length
    }),
    [counterState.items]
  );

  return (
    <CounterContext.Provider value={counterContext}>
      {buttons.map((button, index) => {
        return <MyButton key={index} id={button} />;
      })}
      <Text style={styles.counter}>{counterContext.itemsCount}</Text>
      <Text style={styles.items}>{JSON.stringify(counterContext.items)}</Text>
    </CounterContext.Provider>
  );
}

const styles = StyleSheet.create({
  counter: {
    margin: 10,
    fontSize: 30
  },
  items: {
    margin: 10,
    fontSize: 18
  }
});

MyButton.js MyButton.js

import React from "react";
import { TouchableOpacity, Text, StyleSheet } from "react-native";
import { CounterContext } from "./CounterContext";

export default function MyButton(props) {
  const { addItem } = React.useContext(CounterContext);

  let time = new Date().toLocaleTimeString();

  console.log(time + " - Rendering MyButton #" + props.id + " ...");

  return (
    <TouchableOpacity
      style={styles.myButton}
      onPress={() => {
        addItem({
          name: "Item #" + props.id
        });
      }}
    >
      <Text>Add</Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  myButton: {
    width: 100,
    margin: 10,
    padding: 10,
    textAlign: "center",
    borderWidth: 1,
    borderColor: "#ccc",
    backgroundColor: "#e0e0e0",
    borderRadius: 5
  }
});

Here is the Codesandbox codes: https://codesandbox.io/s/usecontext-dependency-fpcep?file=/src/App.js这是 Codesandbox 代码: https://codesandbox.io/s/usecontext-dependency-fpcep?file=/src/App.js

在此处输入图像描述

Turns out that I have to split Context into two, one that doesn't have dependency, only to run the functions, and one that shows any value(s) real-time by adding the dependency.事实证明,我必须将 Context 分成两部分,一个没有依赖项,只运行函数,另一个通过添加依赖项来实时显示任何值。 The same with the consumer component(s), take it out as new component and put the useContext in there, so parent component won't be re-rendered.与消费者组件相同,将其作为新组件取出并将useContext放入其中,因此不会重新渲染父组件。

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

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