由于前面有 return,因此无法看到条件渲染

Conditional rendering cannot be seen due to a return before them

请帮我起一个更好的标题,我不知道我在问什么。

要理解我的问题,我必须提供我项目的一些背景信息。本来想通过两个按钮有条件地渲染两个页面。按钮 A 呈现屏幕 A 和按钮 B 呈现屏幕 B。在弄清楚如何将状态从 parent 组件传递到 child 及其 child 等之后,我将按钮更改为滑动动画以获得更好的设计。

这会导致问题,因为现在渲染新屏幕时,动画不会显示,因为它只是 re-rendered 与动画中的原始起始位置(我在每个屏幕上都渲染了滑块)。我考虑过提供两个不同的滑块,每个滑块都从相反的方向开始,但仍然会失去整个滑块效果。

我现在已经 渲染了 Slider,所以它一直在那里,而不是 re-rendered。但是我现在已经意识到,如果我在我的条件语句之前 return 它,则永远不会到达该代码。我提供了一个可以完美显示我的问题的工作演示以及下面的代码(我只提供了 App.js,如果需要,其余的在演示中)。我想在 App.js.

中渲染 Slider

工作演示是here,你可以看到滑块没有滑动,它只是改变了屏幕。我需要它滑动。此外,滑动动画仅适用于 iphone,因此我会使用该模拟器而不是网络。

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      whichComponentToShow: "Screen1"
    };
  }

  goToMap = () => {
    this.setState({ whichComponentToShow: "Screen2" });
  };
  goToList = () => {
    this.setState({ whichComponentToShow: "Screen1" });
  };

  render() {
    const { whichComponentToShow } = this.state;
    
    /* This is how I thought I could render this, but obv it makes the rest of the code unreachable.
       How can I render this and then have the conditional page below? Each time the new page renders, 
       it stops the animation from working due to rendering the new page.
    return(
      <Slider/>
    )*/

    if(this.state.whichComponentToShow === 'Screen1'){
        return(
          <View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>

            <ListHome
              renderMap = {this.goToMap.bind(this)}
              renderList = {this.goToList.bind(this)}
            />
          </View>
      );
    }
    else if(this.state.whichComponentToShow === 'Screen2'){
      return(
       <View style={{backgroundColor: '#d1cfcf' ,flex: 1}}>
       
        <MapHome
          renderMap = {this.goToMap.bind(this)}
          renderList = {this.goToList.bind(this)}
        />
  
       </View>
      );
    }

Slider.js(不会出现在零食 apparently

const Slider = (props) => {
  
  const [active, setActive] = useState(false)
  let transformX = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    if (active) {
      Animated.timing(transformX, {
        toValue: 1,
        duration: 300,
        useNativeDriver: true
      }).start()
    } else {
      Animated.timing(transformX, {
        toValue: 0,
        duration: 300,
        useNativeDriver: true
      }).start()
    }
  }, [active]);

  const rotationX = transformX.interpolate({
    inputRange: [0, 1],
    outputRange: [2, Dimensions.get('screen').width / 4]
  })


  return (
    <SafeAreaView style={{
      flex: 1,
      alignItems: 'center'
    }}>
      <View style={{
        flexDirection: 'row',
        position: 'relative',
        height: 45,
        width: 240,
        borderRadius: 10,
        backgroundColor: 'white',
        marginHorizontal: 5
      }}>
        <Animated.View
          style={{
            position: 'absolute',
            height: 45 - 2*2,
            top: 2,
            bottom: 2,
            borderRadius: 10,
            width: Dimensions
            .get('screen').width / 3 - 3.5 ,
            transform: [
              {
                translateX: rotationX
              }
            ],
            backgroundColor: '#d1cfcf',
          }}
        >
        </Animated.View>
        <TouchableOpacity style={{
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center'
        }} onPress={() => {setActive(false); props.renderList() }}>
          <Text>
            List
        </Text>
        </TouchableOpacity>
        <TouchableOpacity style={{
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center'
        }} onPress={() => {setActive(true); props.renderMap() }}>
          <Text>
            Map
        </Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}


export default Slider

我试过你的 expo snack 并没有看到与动画相关的代码,所以我假设 snack 中的代码不是你当前的代码,你确实已经有了一个有效的动画, <Slider ... />.

在您的情况下,要保持 Slider 呈现而不是卸载,您可以做的是在 render() 方法中使用变量。

基本上,您可以将 JSX 分配给一个变量,稍后您可以在另一个 JSX 部分中使用该变量。

key 分配给特定的 JSX 也有助于指导 React 在渲染调用之间这是相同的组件,因此它也可以防止该组件的无意重新渲染。

这是对您在 post 中所写内容的评论的编辑。我希望这是有道理的。

export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            whichComponentToShow: "Screen1"
        };
    }

    goToMap = () => {
        this.setState({ whichComponentToShow: "Screen2" });
    };
    goToList = () => {
        this.setState({ whichComponentToShow: "Screen1" });
    };

    render() {
        const { whichComponentToShow } = this.state;

        /* 
        Keep the slider JSX in a variable to be used.
        Setting a specific key also helps prevent it from being accidentally re-rendered in some conditions.
        )*/
        const sliderRender = <Slider key='slider' />;

        if (this.state.whichComponentToShow === 'Screen1') {
            return (
                <View style={{ backgroundColor: '#d1cfcf', flex: 1 }}>

                    <ListHome
                        renderMap={this.goToMap.bind(this)}
                        renderList={this.goToList.bind(this)}
                    />
                    {/* Put the rendered slider into the render tree */}
                    {sliderRender}
                </View>
            );
        }
        else if (this.state.whichComponentToShow === 'Screen2') {
            return (
                <View style={{ backgroundColor: '#d1cfcf', flex: 1 }}>

                    <MapHome
                        renderMap={this.goToMap.bind(this)}
                        renderList={this.goToList.bind(this)}
                    />
                    {/* Put the rendered slider into the render tree */}
                    {sliderRender}
                </View>
            );
        }
    }
}

编辑:Expo Snack 演示其工作