React Native 防止上下文依赖重新渲染所有组件 [英] React Native Prevent Context Dependency Rerender All Components

查看:50
本文介绍了React Native 防止上下文依赖重新渲染所有组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个按钮.当我单击一个按钮时,它会触发 Context 的备忘录功能以将一个项目添加到 Context 的项目中.我看到单击一个按钮会重新呈现所有三个按钮,这是意料之中的.我只需要重新渲染点击的按钮.请指教.

CounterContext.js

import { createContext } from react";export const CounterContext = createContext(null);

App.js

从反应"导入反应;import { Text, StyleSheet } from react-native";从./MyButton"导入 MyButton;import { CounterContext } from "./CounterContext";函数 counterReducer(prevState, action) {开关(动作.类型){案例ADD_ITEM":让 items = [...prevState.items, action.item];返回 {物品:物品,计数:items.length};默认:console.log(无操作类型");休息;}}const 按钮 = [1"、2"、3"];导出默认函数 App() {const [counterState, counterDispatch] = React.useReducer(counterReducer, {项目: [],计数:0});const counterContext = React.useMemo(() =>({添加项目:项目 =>{counterDispatch({类型:ADD_ITEM",项目:项目});},项目:counterState.items,itemsCount: counterState.items.length}),[counterState.items]);返回 (<CounterContext.Provider value={counterContext}>{buttons.map((button, index) => {返回 <MyButton key={index} id={button}/>;})}<Text style={styles.counter}>{counterContext.itemsCount}</Text><Text style={styles.items}>{JSON.stringify(counterContext.items)}</Text></CounterContext.Provider>);}const 样式 = StyleSheet.create({柜台: {保证金:10,字体大小:30},项目: {保证金:10,字体大小:18}});

MyButton.js

从反应"导入反应;import { TouchableOpacity, Text, StyleSheet } from react-native";import { CounterContext } from "./CounterContext";导出默认函数 MyButton(props) {const { addItem } = React.useContext(CounterContext);让时间 = new Date().toLocaleTimeString();console.log(time + "-Rendering MyButton #" + props.id + "...");返回 (<TouchableOpacitystyle={styles.myButton}onPress={() =>{新增项目({名称:项目#"+ props.id});}}><文本>添加</文本></TouchableOpacity>);}const 样式 = StyleSheet.create({我的按钮:{宽度:100,保证金:10,填充:10,文本对齐:居中",边框宽度:1,边框颜色:#ccc",背景颜色:#e0e0e0",边界半径:5}});

这是 Codesandbox 代码:

解决方案

原来我必须将 Context 拆分为两个,一个没有依赖关系,只运行函数,另一个显示任何值) 实时通过添加依赖项.与消费者组件相同,将其作为新组件取出并放入useContext,这样父组件就不会被重新渲染.

I have three buttons. When I click one button, it fires Context's memo function to add an item into Context's items. 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

import { createContext } from "react";

export const CounterContext = createContext(null);

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

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

解决方案

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

这篇关于React Native 防止上下文依赖重新渲染所有组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆