子组件在道具更新后不会重新渲染

时间:2020-09-16 21:57:25

标签: reactjs react-native

React Native 0.63.2应用程序中有一个父函数组件Itie和一个子组件MyAccordion。想法是在将图片上传到父级Itie中之后,然后应打开子级MyAccordion来显示图片。这是父级Itie中的相关代码:

import MyAccordion from "../app/MyAccordion"; //<<==import child component
export default function Itie({navigation}) {
    const [accordImgOpen, setImgAccordOpen] = useState(false); //<<==define state accorImgOpen

  const addImages = (pics) => {
        if (!pics || pics===[] || pics==={}) return;
        setImgAccordOpen(true); //update accorImgOpen to true in images upload
        //do something...
    };
  const updateImgAccord = (status) => {  //<<==allow update from MyAccordion
        setImgAccordOpen(status);
    };

return (
  <MyAccordion 
                            title={"Image"} 
                            absPosition={false} 
                            initOpen={accordImgOpen} //<<==pass accordImgOpen to child MyAccordion
                            screenSize={{width:screen_width, height:((imgs && imgs.length>9) ? screen_width+(screen_width/3)*(Math.ceil(((imgs.length-9)%3)/3)):screen_width)}} 
                            updateStatus={updateImgAccord} //<<==pass method to MyAccordion
                        >
                            <DisplayImages pics={imgs} deleteImage={deleteImage} updateImage={(new_img)=> {setImgs(new_img)}} swipeImage={(indx) => swipeImage(indx)}/> //<<==display images in child MyAccordion
                        </MyAccordion>
);

在子项MyComponent中,状态open被定义为控制手风琴的打开/关闭:

function MyAccordion({ title, children, updateStatus, initOpen, absPosition=true, screenSize=null }) {  //
  const [open, setOpen] = useState(initOpen);  //<<==initial value of open is from parent

  const toggleListItem = () => {  //<<==open/close accordion by state open
    console.log("Accordion status : ", open);
    if (open) {
      Animated.timing(animatedController, {
        duration: 300,
        toValue: 1,
        easing: Easing.bezier(0.4, 0.0, 0.2, 1),
        useNativeDriver:false,
      }).start();
    } else {
      Animated.timing(animatedController, {
        duration: 300,
        toValue: 0,
        easing: Easing.bezier(0.4, 0.0, 0.2, 1),
        useNativeDriver:false,
      }).start();
    }
    setOpen(!open); //update state open
    updateStatus(!open); //update parent state (accordImgOpen)
  };

  return (
    <>
      <TouchableWithoutFeedback onPress={() => toggleListItem()}>  //<<==toggleListItem is called with user click
        <View style={styles.titleContainer}>
          <Text>{title}</Text>
          <Animated.View style={{ transform: [{ rotateZ: arrowAngle }] }}>
            <Icon name="chevron-down-outline" size={20}  />
          </Animated.View>
        </View>
      </TouchableWithoutFeedback>
      <Animated.View style={[styles.bodyBackground, { height: bodyHeight }]}>
        <View
          style={[(absPosition ? styles.bodyContainerAbs : styles.bodyContainerCenter), (screenSize ? {width:screenSize.width, height:screenSize.height} : null)]}
          onLayout={event => {
            if (screenSize) {
              setBodySectionHeight(screenSize.height);
            } else {
              setBodySectionHeight(event.nativeEvent.layout.height);
            };
            console.log("layout : ", event.nativeEvent.layout);
          }
          }>
          {children}
        </View>
      </Animated.View>
    </>
  );
};

问题在于,当父MyAccordion中上载的图像和Itie中的状态open未相应更新时,子MyAccordion不会重新渲染。这里缺少什么?我是否应将状态open放入子return的{​​{1}}中以强制重新渲染?

0 个答案:

没有答案