0

I have a configurable application which everything is fed into the app from a middleware (like colors and contents) based on a unique id so-called appId. In the home screen, I am fetching all required data from a middleware in componentDidMount() function and then use it later on. For the first time, I am using a default appId and the componentDidMount() looks like this:

componentDidMount() {
this.setState({ isLoading: true });
fetch(
  API +
    "configurations" +
    "?" +
    "uuid=blabla" +
    "&" +
    "appId=" +
    appId +
    "&" +
    "locale=" +
    locale +
    "&" +
    "gid=" +
    gid,
  {
    method: "GET",
    headers: {
      Accept: "application/json"
    }
  }
)}

I have another screen (settings screen) where I have a box and the user can insert appId as input.

When the appId is inserted by the user (in the settings page), I would like to navigate back to the Home screen and re-fetch the data with the new appId that was inserted by the user. The setting screen looks like this:

state = {
newappId: "" };

handlenewappId = text => {
this.setState({ newappId: text });
};

.....

<Item regular>
          <Input
            onChangeText={this.handlenewappId}
            placeholder="Regular Textbox"
          />
          <Button
            onPress={() => {
              navigation.navigate("Home");
            }}
          >
            <Text>Save</Text>
          </Button>
</Item>

However, when I do navigation.navigate("Home") the componentDidMount() is not triggered in order to fetch the data again from the middleware (which is expected since it is only triggered for the first time). What should I do? What is the solution?

I have already tried the solution given in `componentDidMount()` function is not called after navigation but it didn't work for me.

also tried to move the code in componentDidMount() into a separate function and call it from the settings page but I couldn't make it work.

============== UPDATE: ==============

I was able to solve the issue with the answer given by "vitosorriso" below. However, a new issue occurs. After fetching is done, I am pushing the response to the state and then use it my home screen like this:

fetchData = async () => {
this.setState({ isLoading: true }, async () => {
   //fetch the data and push the response to state. e.g:

   this.setState({ page: data, configs: data2, isLoading: false });

}}
....

render() {
const { configs, page, isLoading, error } = this.state; //getting the data fetched in the fetch function and pushed to the state

if (isLoading || !page || !configs) { 
   //if data is not ready yet
  );

// Use the data to extract some information

let itemMap = page.item.reduce((acc, item) => {
  acc[item.id] = item;
  item.attributes = item.attributes.reduce((acc, item) => {
    acc[item.key] = item.value;
    return acc;
  }, {});
  return acc;
}, {});
}}

For the first time the app starts, everything works fine and there is no error but if I go to the settings page and press the button to navigate back to the home screen and fetch data again, I face the error: "items.attributes.reduce is not a function". I am assuming the reason is, "items.attributes" already has a value (from the first time) and can't fed with new data again.

Is there any way, to clear all the variables when navigating from settings page to the home page?

Mehdi Satei
  • 1,225
  • 9
  • 26

1 Answers1

0

I have solved the same problem in my app with a similar concept of this ( `componentDidMount()` function is not called after navigation ) but using a different syntax, and it is working for me:

// your home class
// no need to import anything more

// define a separate function to fetch data
fetchData = async () => {
  this.setState({ isLoading: true }, async () => {
    // fetch your data here, do not forget to set isLoading to false
  }
}

// add a focus listener onDidMount
async componentDidMount () {
  this.focusListener = this.props.navigation.addListener('didFocus', async () => {
    try {
      await this.fetchData() // function defined above
    } catch (error) {
      // handle errors here
    }
  })
}

// and don't forget to remove the listener
componentWillUnmount () {
  this.focusListener.remove()
}
vitosorriso
  • 765
  • 1
  • 7
  • 16
  • Great!! That actually solved my problem but I faced a new issue. As I said, for the first time when I fetch the data, I extract some data from it. The next time when I navigate back to the home screen to fetch the new data, since the variables are previously filled with data, error occurs. e.g: the first time the data is fetched, a variable is like: let itemMap = page.item.reduce((acc, item) => { item.attributes = item.attributes.reduce((acc, item) => {..}} Everything is fine for the first time but when I navigate back from settingspage, it says: "item.attributes.reduce is not a function" – Mehdi Satei May 01 '19 at 17:49
  • I am wondering how I can re-value the variables. In the debugger, the error is "Extra Data". I am guessing the reason is bcz variables have been defined and valued once before and can't be re-valued. – Mehdi Satei May 01 '19 at 17:53
  • Could you be more specific and edit the question, pasting more code (at least the code related to itemMap)? thanks – vitosorriso May 01 '19 at 18:04
  • I edited the question with more details. Let me know if you need more details – Mehdi Satei May 01 '19 at 18:31
  • Ok great. First of all, you have to avoid do some stuff with data into the render() method. It's a bad habit, since everytime a render occurs, that itemMap is reallocated. Try to extract data and calculate itemMap into a separate function, assing it to a state variable and refer into your component to it as this.state.itemMap – vitosorriso May 01 '19 at 18:41