天然 reactjs :redux-toolkit状态改变时如何重新呈现memo组件

pftdvrlh  于 2022-12-27  发布在  React
关注(0)|答案(1)|浏览(150)

我有一个由flatList呈现的产品列表,在组件内部,我请求一个产品图像并将其存储在redux存储中,问题是当图像更新时,组件不会重新呈现
产品视图组件:

const ProductView: FC<Props> = ({ price }: Props): ReactElement => {
  const basketItem = useReduxSelector((state) =>
    state.basket.items.find((item) => item.item.id === price.id)
  );
  const productImage = useReduxSelector(state => state.product.productImage.find((item) => item.id === price.id));
  const [isFocused, setIsFocused] = useState<boolean>(false);
  const [image, setImage] = useState<string>(productDefaultImage);
  const useDispatch = useReduxDispatch();

  useEffect(() => {
    const getProductImage = async () => {
      const token: string | null = await localStorage.getValue("token");

      getProductImageById(token!, price.id.toString())
        .then((res) => {
          if (res.data.fileContent !== "") {
            useDispatch(updateProductImage({ id: price.id, fileName: res.data.fileName, fileContent: `data:image/jpeg;base64,${res.data.fileContent}` }))
          } else if (res.data.fileContent === "") {
            setImage(productDefaultImage);
          }
        })
        .catch((error) => {
          console.log(error);
        });
    };
    if (!productImage)
      getProductImage();
    else setImage(productImage.fileContent)
  });

  console.log('Rendering product item with id:', price.priceId);

  return (
    <Layout style={styles.container}>
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Image
          source={{
            uri: image
          }}
          resizeMode="contain"
          style={{ width: 100, height: 70 }}
        />
        <View style={styles.priceContainer}>
          <Text style={styles.priceText}>{price.price}</Text>
          <Text style={styles.currencyText}>دم</Text>
        </View>
        <PriceType
          quantityType={
            price.sellUnit === SellUnitEnum.ATOMIC
              ? price.atomicRtlName
              : price.packingRtlName
          }
        />
      </View>
      <View style={{ flex: 3 }}>
        <View
          style={{
            flex: 1,
            flexDirection: "row-reverse",
            justifyContent: "space-between",
            alignItems: "center",
          }}
        >
          <Text
            style={{
              width: "75%",
              textAlign: "right",
              fontFamily: "almarai-bold",
              marginRight: 3,
            }}
          >
            {price.rtlName}
          </Text>
          {price.withPoints ? <AwalPoint points={price.points} backgroundColor={Colors.gray200} textColor={Colors.gray800} /> : <View></View>}
        </View>
        <View style={{ flex: 1, flexDirection: "row-reverse" }}>
          <PackageQuantity
            title={price.atomicRtlName.toString() + " في"}
            packageName={price.packingRtlName}
            quantity={price.packageQuantity.toString()}
            image={require("../assets/surprise.png")}
            backgroundColor={Colors.primary400}
            containerStyle={{ flex: 1 }}
          />
          <PackageQuantity
            title="تمن"
            packageName={
              price.sellUnit === "ATOMIC"
                ? price.packingRtlName
                : price.atomicRtlName
            }
            quantity={
              (price.sellUnit === "ATOMIC"
                ? (price.price * price.packageQuantity).toFixed(2)
                : (price.price / price.packageQuantity).toFixed(2)
              ).toString() + " دم"
            }
            image={require("../assets/dollar.png")}
            backgroundColor={Colors.secondary400}
            containerStyle={{ flex: 1.5 }}
          />
        </View>
        <View style={{ flex: 1, flexDirection: "row", paddingBottom: 7 }}>
          {basketItem === undefined && !isFocused ? (
            <Button
              style={{
                height: 45,
                borderWidth: 0,
                borderRadius: 100,
                backgroundColor: Colors.secondary500,
              }}
              onPress={() => {
                useDispatch(updateItems({ item: price, quantity: 1, error: undefined, productImage: image }));
              }}
              accessoryRight={IconComponent(evaIcons.cart, Colors.white500)}
            >
              {(props) => (
                <Text
                  {...props}
                  style={{
                    fontFamily: "almarai-bold",
                    fontSize: 15,
                    color: Colors.white500,
                  }}
                >
                  أضف إلى السلة
                </Text>
              )}
            </Button>
          ) : (
            <CounterInput
              style={{ flex: 1 }}
              priceId={price.id}
              isFocused={isFocused}
              setIsFocused={setIsFocused}
              maxValue={price.storeQuantity}
              buttonStyle={{ backgroundColor: Colors.primary500, borderWidth: 0 }}
            />
          )}
          <View style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end' }}>
            {(price.isDiscountable === true) ?
              <View style={{ flexDirection: 'row-reverse', justifyContent: 'center', alignItems: 'center' }}>
                <Image
                  source={require("../assets/promo.png")}
                  resizeMode="contain"
                  style={{ width: 30, height: 30 }}
                />
                <Text style={{ textAlign: 'center', fontFamily: 'almarai-regular' }}>فيه روميز</Text>
              </View> : null}
          </View>
        </View>
      </View>
    </Layout>
  );
};
const isChanged = (prev: Props, next: Props) => {
  return prev.price === next.price;
}

export default memo(ProductView, isChanged)

目标:我想在图像状态改变时重新渲染组件,有什么方法可以做到吗?

ve7v8dk2

ve7v8dk21#

在阅读了更多关于备忘录的内容之后,我发现了名为useMemo()的react钩子,因此通过将useEffect()钩子替换为useMemo(),修复了我的问题

useMemo(() => {
    const getProductImage = async () => {
      const token: string | null = await localStorage.getValue("token");

      getProductImageById(token!, price.id.toString())
        .then((res) => {
          if (res.data.fileContent !== "") {
            useDispatch(updateProductImage({ id: price.id, fileName: res.data.fileName, fileContent: `data:image/jpeg;base64,${res.data.fileContent}` }))
          }
        })
        .catch((error) => {
          console.log(error);
        });
    };

    if (!productImage)
      getProductImage();
    else setImage(productImage.fileContent)
  }, [productImage?.fileContent])

相关问题