1

我试图让一个组件出现在其他组件之间。为此,我想创建一个通用包装器,能够计算其子组件的大小并创建正确的动画。

到目前为止,当子元素的大小被硬编码时,我成功地(遇到了很多麻烦)以某种方式使组件按预期显示。但是一旦设置了填充或边距,它就不起作用了......

在这里查看我的测试用例:

import React from "react";
import ReactDOM from "react-dom";

import { View, Text, TouchableOpacity } from "react-native-web";
import styled from "styled-components";

const Container = styled(View)`
  flex-direction: row;
`;

//The button that will make the component appear
class Toggle extends React.PureComponent {
  render() {
    return (
      <TouchableOpacity {...this.props}>
        <Text>Press Me</Text>
      </TouchableOpacity>
    );
  }
}

//This wrapper will carry the appearing animation
const Wrapper = styled(View)`
  transition: all ${props => props.delay}s ease;
  transform: scale(${props => (props.mount ? 1 : 0)});
  width: ${props => (props.mount ? props.width : 0)}px;
`;

//This is the component in charge of the appearing effect
class Appearing extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      mounted: false,
      render: false,
      width: 0
    };
  }

  //This will start the animation
  componentDidMount() {
    this.setState({ mounted: true, render: true });
  }

  componentDidUpdate() {
    //this will start the disappearing animation
    if (this.state.mounted && !this.props.mount) {
      this.setState({ mounted: false });
      setTimeout(
        () => this.setState({ render: false }),
        this.props.delay * 1000
      );
      //this will restart the appearing animation
    } else if (!this.state.mounted && this.props.mount) {
      this.setState({ mounted: true, render: true });
    }
    //We read the expected this of the child component
    this.setState({ width: this.getWidth ? this.getWidth() : 0 });
  }

  render() {
    return (
      <Wrapper {...this.props} width={this.state.width}>
        {React.cloneElement(this.props.children, {
          //We read the child size with the 'onLayout' method
          onLayout: event =>
            (this.getWidth = () => event.nativeEvent.layout.width)
        })}
      </Wrapper>
    );
  }
}

//Carry the test case
class App extends React.PureComponent {
  state = { toggle: false };
  render() {
    return (
      <View>
        {/* with only the width set */}
        <Container>
          <Appearing delay={0.5} mount={this.state.toggle}>
            <Text style={{ width: "9em" }}>Tadaaaaaaaa !</Text>
          </Appearing>
          <Toggle
            onPress={() => this.setState({ toggle: !this.state.toggle })}
          />
        </Container>
        {/* with the width and padding set */}
        <Container>
          <Appearing delay={0.5} mount={this.state.toggle}>
            <Text style={{ width: "9em", paddingLeft: "10em" }}>
              Tadaaaaaaaa !
            </Text>
          </Appearing>
          <Toggle
            onPress={() => this.setState({ toggle: !this.state.toggle })}
          />
        </Container>
      </View>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

您知道实现这一目标的最佳方法吗?

4

0 回答 0