You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何将子组件的变量传递给父组件?

解决方案

方案1:通过共同父组件传递状态(最直接)

如果Banner和TabScreen有共同的父组件,这是最简单的实现方式:

  1. 父组件维护bannerImageHeight状态
  2. 给Banner传递回调函数,计算出imageHeight后更新父组件状态
  3. 将父组件的bannerImageHeight作为props传给TabScreen

示例代码:

父组件

const ParentComponent = () => {
  const [bannerImageHeight, setBannerImageHeight] = useState(0);

  return (
    <>
      <Banner onImageHeightChange={setBannerImageHeight} />
      <TabScreen bannerHeight={bannerImageHeight} />
    </>
  );
};

修改后的Banner组件

const Banner = ({ onImageHeightChange }) => {
  const [AdData, setAdData] = useState();
  const [showBanner, setShowBanner] = useState(false);
  const [currentIndex, setCurrentIndex] = useState(0);

  const imageHeight = MiscUtils.returnDefaultValueIfNotValid(0, AdData, 'fetchAds', 'ads', currentIndex, 'image', 'height');

  // 高度变化时通知父组件
  useEffect(() => {
    onImageHeightChange(imageHeight);
  }, [imageHeight, onImageHeightChange]);

  return (
    <Image 
      style={Styles.image}
      resizeMode={'stretch'}
      source={{uri: imageUrl}}
      height={imageHeight}
    />
  );
};
export default Banner;

修改后的TabScreen组件

const TabScreen = ({ bannerHeight }) => {
  useEffect(() => {
    if(ref.current && !isScrollOnTop(ref.current.getCurrentScrollOffset())) {
      const offsetChange = isDisplayAdBannerVisible ? bannerHeight : -bannerHeight;
      ref.current.scrollToOffset(0, ref.current.getCurrentScrollOffset() + offsetChange, true);
    }
  }, [bannerHeight, isDisplayAdBannerVisible]); // 务必添加依赖项

  // 其他组件代码...
};

export default React.memo(TabScreen);

方案2:使用React Context(跨层级组件共享)

如果两个组件层级较深、没有直接共同父组件,用Context更合适:

  1. 创建存储banner高度的Context
  2. 在顶层组件用Context.Provider包裹组件树
  3. 在Banner中更新Context值,TabScreen中订阅Context

示例代码:

创建BannerContext.js

import { createContext, useState, useContext } from 'react';

const BannerContext = createContext();

export const BannerProvider = ({ children }) => {
  const [bannerHeight, setBannerHeight] = useState(0);

  return (
    <BannerContext.Provider value={{ bannerHeight, setBannerHeight }}>
      {children}
    </BannerContext.Provider>
  );
};

export const useBannerHeight = () => useContext(BannerContext);

修改Banner组件

import { useBannerHeight } from './BannerContext';

const Banner = () => {
  const [AdData, setAdData] = useState();
  const [showBanner, setShowBanner] = useState(false);
  const [currentIndex, setCurrentIndex] = useState(0);
  const { setBannerHeight } = useBannerHeight();

  const imageHeight = MiscUtils.returnDefaultValueIfNotValid(0, AdData, 'fetchAds', 'ads', currentIndex, 'image', 'height');

  useEffect(() => {
    setBannerHeight(imageHeight);
  }, [imageHeight, setBannerHeight]);

  return (
    <Image 
      style={Styles.image}
      resizeMode={'stretch'}
      source={{uri: imageUrl}}
      height={imageHeight}
    />
  );
};
export default Banner;

修改TabScreen组件

import { useBannerHeight } from './BannerContext';

const TabScreen = () => {
  const { bannerHeight } = useBannerHeight();

  useEffect(() => {
    if(ref.current && !isScrollOnTop(ref.current.getCurrentScrollOffset())) {
      const offsetChange = isDisplayAdBannerVisible ? bannerHeight : -bannerHeight;
      ref.current.scrollToOffset(0, ref.current.getCurrentScrollOffset() + offsetChange, true);
    }
  }, [bannerHeight, isDisplayAdBannerVisible]);

  // 其他组件代码...
};

export default React.memo(TabScreen);

方案3:修复Redux实现(若仍想用Redux)

如果之前Redux没成功,大概率是状态更新或订阅环节出了问题,正确实现方式如下:

  1. 定义action类型和创建函数
// actions.js
export const SET_BANNER_HEIGHT = 'SET_BANNER_HEIGHT';
export const setBannerHeight = (height) => ({
  type: SET_BANNER_HEIGHT,
  payload: height
});
  1. 更新reducer
// reducer.js
import { SET_BANNER_HEIGHT } from './actions';

const initialState = {
  bannerHeight: 0
};

export const appReducer = (state = initialState, action) => {
  switch(action.type) {
    case SET_BANNER_HEIGHT:
      return { ...state, bannerHeight: action.payload };
    default:
      return state;
  }
};
  1. 在Banner中dispatch action
import { useDispatch } from 'react-redux';
import { setBannerHeight } from './actions';

const Banner = () => {
  const [AdData, setAdData] = useState();
  const [showBanner, setShowBanner] = useState(false);
  const [currentIndex, setCurrentIndex] = useState(0);
  const dispatch = useDispatch();

  const imageHeight = MiscUtils.returnDefaultValueIfNotValid(0, AdData, 'fetchAds', 'ads', currentIndex, 'image', 'height');

  useEffect(() => {
    dispatch(setBannerHeight(imageHeight));
  }, [imageHeight, dispatch]);

  return (
    <Image 
      style={Styles.image}
      resizeMode={'stretch'}
      source={{uri: imageUrl}}
      height={imageHeight}
    />
  );
};
export default Banner;
  1. 在TabScreen中用useSelector获取状态
import { useSelector } from 'react-redux';

const TabScreen = () => {
  const bannerHeight = useSelector(state => state.app.bannerHeight);

  useEffect(() => {
    if(ref.current && !isScrollOnTop(ref.current.getCurrentScrollOffset())) {
      const offsetChange = isDisplayAdBannerVisible ? bannerHeight : -bannerHeight;
      ref.current.scrollToOffset(0, ref.current.getCurrentScrollOffset() + offsetChange, true);
    }
  }, [bannerHeight, isDisplayAdBannerVisible]);

  // 其他组件代码...
};

export default React.memo(TabScreen);

注意事项

  • 所有方案都要确保useEffect的依赖项完整,避免遗漏状态更新或不必要的重复渲染
  • 若imageHeight初始值为0,建议在TabScreen中添加 fallback 逻辑(比如默认用65)

内容的提问来源于stack exchange,提问作者Kumar Shivam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:55:24