1

First, thanks for reading me. I'm working on react-native using Expo. I set up functions in my app using componentWillMount and componentDidMount. It's working, ok but I have difficulties understanding why my component renders 4 times...

I get this result (with my console.log) :

Results retrieveDeviceManufacturer() : 42 ===>retrieveProfileUserId 42 Results retrieveDeviceUID() : ... Results retrieveDeviceOSVersion() : 10 Results retrieveDeviceManufacturer() : Google Connection type wifi Is connected? true

But 4 times in a row each times I execute the component. I'm of course new to react-native and need help to fully understand this.

Thanks a lot if you can help. Here is my full page of code :

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isFirstConnection: true };
    status: "0";
    deviceOSVersion: null;
    deviceManufacturer: null;
    deviceUID: null;
    profileUserId: null;
  }

  performTimeConsumingTask = async () => {
    return new Promise(resolve =>
      setTimeout(() => {
        resolve("result");
      }, 1000)
    );
  };
  componentWillMount = async () => {
    this.setState({ deviceOSVersion: await retrieveDeviceOSVersion() });
    this.setState({ deviceManufacturer: await retrieveDeviceManufacturer() });
    this.setState({ deviceUID: await retrieveDeviceUID() });
    this.setState({ profileUserId: await retrieveProfileUserId() });
  };

  async componentDidMount() {
    this.setState({ status: "6" });
    // Preload data from an external API
    // Preload data using AsyncStorage
    const data = await this.performTimeConsumingTask();

    if (data !== null) {
      this.setState({ isFirstConnection: false });
    }

    Font.loadAsync({
      Roboto: require("./assets/fonts/Roboto-Black.ttf")
    });
  }

  render() {
    if (this.state.status == "6") {
      console.log(
        "Results retrieveDeviceManufacturer() : ",
        this.state.profileUserId
      );
      if (this.state.profileUserId !== null && this.state.profileUserId > 0) {
        // OK
      } else {
        // Need connection
      }
      console.log("===>retrieveProfileUserId", this.state.profileUserId);

      // Device UUID
      console.log("Results retrieveDeviceUID() : ", this.state.deviceUID);
      if (this.state.deviceUID !== null) {
        // OK
      } else {
        // TODO : next step...
        storeDeviceUID(getDeviceUID());
      }

      // Detect Manufacturer : iOS, Android, ..
      if (this.state.deviceManufacturer !== null) {
        // OK
      } else {
        storeDeviceManufacturer(getDeviceManufacturer());
      }

      // Get system version
      if (this.state.deviceOSVersion !== null) {
        // OK
      } else {
        storeDeviceOSVersion(getDeviceOSVersion());
      }

      console.log(
        "Results retrieveDeviceOSVersion() : ",
        this.state.deviceOSVersion
      );
      console.log(
        "Results retrieveDeviceManufacturer() : ",
        this.state.deviceManufacturer
      );

      NetInfo.fetch().then(state => {
        console.log("Connection type", state.type);
        console.log("Is connected?", state.isConnected);
      });
      if (this.state.isFirstConnection) {
        return <SplashScreen />;
      }
      return <Navigation />;
    } else {
      console.log("STATUS INITIALISATION");
      this.setState({ status: "1" });
      return null;
    }
  }
}
Kimako
  • 615
  • 2
  • 11
  • 26

3 Answers3

1

see the reason why your console.log prints 4 times inside the render fnuction is because you have added 4 setState functions inside the componentWillMount ,

componentWillMount = async () => {
    this.setState({ deviceOSVersion: await retrieveDeviceOSVersion() });
    this.setState({ deviceManufacturer: await retrieveDeviceManufacturer() });
    this.setState({ deviceUID: await retrieveDeviceUID() });
    this.setState({ profileUserId: await retrieveProfileUserId() });
  };

So every instance of setState will again re-render the app , that is call the render function again , so it's a bad practice and hence render function is called 4 times. try writing everything in on SetState,

componentWillMount = async () => {
        this.setState({ deviceOSVersion: await retrieveDeviceOSVersion(),deviceManufacturer: await retrieveDeviceManufacturer() ,
deviceUID: await retrieveDeviceUID(),profileUserId: await retrieveProfileUserId()});

      };

And try using comopnentDidmount in place of componentWillMount since it will be deprecated. hope it helps

Gaurav Roy
  • 11,175
  • 3
  • 24
  • 45
0

From what I can see from your code, in the componentWillMount you are calling setState 4 times. Generally speaking, whenever there is a change of state using setState, React is going to rerender the component. You are calling it 4 times - you get 4 rerenders (that's one possibility).

For additional info please refer here

I would not worry about it until you start to notice problems with the performance of your app, in which case I would think about optimization. But not beforehand.

Moreover, componentWillMount has been deprecated and you shouldn't be using it in your components. Please refer here.

Hope this helps!

Konstantin
  • 1,390
  • 6
  • 18
0

Does React re-render all components and sub components every time setState is called?

the default answer is yes.

Ankit Jain
  • 30
  • 3