Home > OS >  ComponentDidMount vs useEffect
ComponentDidMount vs useEffect

Time:10-04

There is a class components work piece. I want to convert it into a function component and implement it in the same way, but there's a problem.

Unlike the class type, the function type returns to the place where it was created without staying after the picture has moved.

This is the function components.

const [dogs, setDogs] = useState([])

function addDog(){
    // setDogs([...dogs, {id: dogCount  }])
    dogCount  ;
    console.log(dogCount)
    // console.log(dogs)
    const newDog = {id: dogCount, bottom: 125}
    setDogs([...dogs, newDog])
  }
  
 return (
    <View style={styles.entirebottomsheet}>
      <View style={styles.container}>
        <TouchableOpacity onPress={()=>{addDog();}} style={styles.dogButton}>
          <Text>Dog</Text>
        </TouchableOpacity>
         {dogs.map(dog => {
           return ( 
            <DogContainer
              key={dog.id}
              style={{bottom: dog.bottom, position: 'absolute'}}
            />
          ); 
         })}
      </View>
    </View>
  );
  
  
  function DogContainer () {
  const positionX = new Animated.Value(0);
  const positionY = new Animated.Value(0);
  
  // DogContainer.defaultProps = {
  //   onComplete() {}
  // }

  const getDogStyle = () => ({
    transform: [{translateX: positionX}],
  });

  useEffect(() => {
    Animated.spring(positionX, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start();
    Animated.spring(positionY, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start();
    return (
      console.log('finish')
    )
  }, []);


  return (
    <Animated.View style={[{ bottom: 125},{
      transform: [{translateX: positionX}, {translateY: positionY}],
    }]}>
      <Image source={dogImg} style={{width: 60, height: 60}}/>
    </Animated.View>
  );
}

This is the class components.

export default class App extends React.Component {
  // let {up} = this.props.up;

  state = {
    dogs: [],
    cats: [],
    chicks: [],
  };

  addDog = () => {
    console.log(...this.state.dogs);
    this.setState(
      {
        dogs: [
          ...this.state.dogs,
          {
            id: dogCount,
            bottom: 125,
          },
        ],
      },
      () => {
        dogCount  ;
      },
    );
  };

  removeDog = id => {
    this.setState({
      dogs: this.state.dogs.filter(dog => {
        return dog.id !== id;
      }),
    });
  };

  addCat = () => {
    console.log(...this.state.cats);
    this.setState(
      {
        cats: [
          ...this.state.cats,
          {
            id: catCount,
            bottom: 125,
          },
        ],
      },
      () => {
        catCount  ;
      },
    );
  };

  removeCat = id => {
    this.setState({
      cats: this.state.cats.filter(cat => {
        return cat.id !== id;
      }),
    });
  };

  addChick = () => {
    console.log(...this.state.chicks);
    this.setState(
      {
        chicks: [
          ...this.state.chicks,
          {
            id: chickCount,
            bottom: 125,
          },
        ],
      },
      () => {
        chickCount  ;
      },
    );
  };

  removeChick = id => {
    this.setState({
      chicks: this.state.chicks.filter(chick => {
        return chick.id !== id;
      }),
    });
  };

  render() {
    return (
      <GestureHandlerRootView>
      <View style={styles.entirebottomsheet}>
        <View style={styles.container}>
            <TouchableOpacity onPress={this.addDog} style={styles.dogButton}>
              <Text>Dog</Text>
            </TouchableOpacity>
          {this.state.dogs.map(dog => {
            return (
              <DogContainer
                key={dog.id}
                style={{bottom: dog.bottom, position: 'absolute'}}
                onComplete={() => this.removeDog(dog.id)}
              />
            );
          })}
        </View>

        <View style={styles.container}>
          <TouchableOpacity onPress={this.addCat} style={styles.catButton}>
            <Text>Cat</Text>
          </TouchableOpacity>
          {this.state.cats.map(cat => {
            return (
              <CatContainer
                key={cat.id}
                style={{bottom: cat.bottom, position: 'absolute'}}
                onComplete={() => this.removeCat(cat.id)}
              />
            );
          })}
        </View>

        <View style={styles.container}>
          <TouchableOpacity onPress={this.addChick} style={styles.chickButton}>
            <Text style={{position: 'absolute'}}>Chick</Text>
          </TouchableOpacity>
          {this.state.chicks.map(chick => {
            return (
              <ChickContainer
                key={chick.id}
                style={{bottom: chick.bottom, position: 'absolute'}}
                onComplete={() => this.removeChick(chick.id)}
              />
            );
          })}
        </View>
      </View>
      </GestureHandlerRootView>
    );
  }
}

class DogContainer extends React.Component {
  state = {
    position: new Animated.ValueXY({
      x: 0,
      y: 0,
    }),
  };

  static defaultProps = {
    onComplete() {},
  };

  componentDidMount() {
    Animated.spring(this.state.position.x, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(this.props.onComplete);

    Animated.spring(this.state.position.y, {
      duration: 1000,
      toValue: -340,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(this.props.onComplete);
  }

  getDogStyle() {
    return {
      transform: [
        {translateY: this.state.position.y},
        {translateX: this.state.position.x},
      ],
    };
  }

  render() {
    return (
      <Animated.View style={[this.getDogStyle(), this.props.style]}>
        <Image source={dogImg} style={{width: 60, height: 60, borderRadius: 30}} />
      </Animated.View>
    );
  }
}

CodePudding user response:

Try to use useRef() hook

    function DogContainer () {
          const positionX = useRef(new Animated.Value(0)).current;
          const positionY = useRef(new Animated.Value(0)).current;
...

CodePudding user response:

In the Class-based version of DogContainer the position coordinate was a part of state.

class DogContainer extends React.Component {
  state = {
    position: new Animated.ValueXY({
      x: 0,
      y: 0,
    }),
  };

  static defaultProps = {
    onComplete() {},
  };

  componentDidMount() {
    Animated.spring(this.state.position.x, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(this.props.onComplete);

    Animated.spring(this.state.position.y, {
      duration: 1000,
      toValue: -340,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(this.props.onComplete);
  }

  getDogStyle() {
    return {
      transform: [
        {translateY: this.state.position.y},
        {translateX: this.state.position.x},
      ],
    };
  }

  render() {
    return (
      <Animated.View style={[this.getDogStyle(), this.props.style]}>
        <Image source={dogImg} style={{width: 60, height: 60, borderRadius: 30}} />
      </Animated.View>
    );
  }
}

Function component using the useState hook

function DogContainer ({ onComplete = () => {} }) {
  const [position, setPosition] = React.useState(
    new Animated.ValueXY({
      x: 0,
      y: 0,
    })
  );

  const getDogStyle = () => ({
    transform: [{
      translateX: position.x,
      translateY: position.y,
    }],
  });

  useEffect(() => {
    Animated.spring(position.x, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(onComplete);
    Animated.spring(position.y, {
      duration: 1000,
      toValue: width / 3,
      easing: Easing.ease,
      useNativeDriver: true,
    }).start(onComplete);

    console.log('finish');
  }, []);

  return (
    <Animated.View
      style={[
        { bottom: 125},
        { transform: [
            { translateX: position.x },
            { translateY: position.y }
          ],
        }
      ]}
    >
      <Image source={dogImg} style={{ width: 60, height: 60 }} />
    </Animated.View>
  );
}
  • Related