1

For example:

We have in the constructor the avatar data, inside the avatar there is thumb and inside the thumb the url. I just want to get the url. anyone has any hint to spare?

{avatar: {:thumb{:url}}}


   constructor(props) {
        super(props);

        this.state = {
            id: "",
            avatar: "",
            bio: "",
            error: "",
        }
    }

enter image description here

fetched user data

  async fetchUserId()  {

         let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);



  fetch("https://xxx.herokuapp.com/api/users/"+auth_token+"", {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },

}).then((response) => response.json())
   .then((json) => {


    this.state.id = json.id

//this.state.url =  json.avatar.thumb.url



  })
    .catch((error) => {
      console.error(error);
    });

}
  • Possible duplicate of [How to update a nested state in React](https://stackoverflow.com/questions/43040721/how-to-update-a-nested-state-in-react) – Ahmad Maleki Jul 28 '18 at 05:15

3 Answers3

0

Update:

you're not setting json.id and json.avatar correctly to the state you need to use setState

this.setState({ id: json.id,avatar: json.avatar })

Solution one

 constructor(props) {
        super(props);

        this.state = {
            id: "",
            avatar: {},
            bio: "",
            error: "",
            url: ""
        }

    }

getUrl = () =>{
if(this.state.avatar && this.state.avatar.thumb && this.state.avatar.thumb.url){
      this.setState({ url: this.state.avatar.thumb.url })
   } 
}

<button onClick={this.getUrl}>Get URL </button>

Solution Two

Because avatar is coming from async I suggest you to use componentWillUpdate lifecycle method

componentWillUpdate(nextProps, nextState){
   if(this.state.avatar !== nextState.avatar){
     console.log(nextState.avatar.thumb.url)
   }
}

Note: componentWillUpdate will invoket on everytime that this.state.avatar changes

Liam
  • 6,517
  • 7
  • 25
  • 47
  • Liam, thank you very much for your interest and answer but after i added your answer show this error in the logs TypeError: TypeError: TypeError: TypeError: undefined is not an object (evaluating '_this.state.avatar.thumb.url') –  Jul 28 '18 at 04:46
  • I just edit my answer. Is `avatar` data coming from async operation? – Liam Jul 28 '18 at 04:48
  • i'm fetching and parsing into json –  Jul 28 '18 at 04:53
  • but anyway thank you very much for your time and patience –  Jul 28 '18 at 05:08
  • wait a minute just let check this avatar: {} –  Jul 28 '18 at 05:09
  • this (evaluating '_this.state.avatar.thumb.url') –  Jul 28 '18 at 05:12
  • Ok no worries, I will edit my answer, this occurs because `avatar` data isn't exist yet. – Liam Jul 28 '18 at 05:14
  • liam thank you, i update the question as well, as you was wondering how i was get the user data –  Jul 28 '18 at 05:34
  • @lula check now – Liam Jul 28 '18 at 05:46
0

Since you cannot mutate the state, and since setState doesn't handle nested updates, you need to use the following code to set such a state:

this.setState(prevState => ({
    ...prevState,
    avatar: {
        ...prevState.avatar,
        thumb: {
           ...prevState.avatar.thumb,
           url: newUrlValue
        }
    }
}))
Yossi
  • 5,577
  • 7
  • 41
  • 76
  • The `...prevState` before `avatar: {` is not necessary because `setState` automatically handles that. – Ahmad Maleki Jul 28 '18 at 05:12
  • Rahamin, thank you but in newUrlValue should i place the fetched data? –  Jul 28 '18 at 05:29
  • Which data do you fetch? A url? Then, yes. From your state definition I understood that you want to know how to set the url value inside the state... – Yossi Jul 28 '18 at 06:11
0

Like This You can set:-

class App extends Component {
  state = {
    name: "",
    stars: "",
    icon: "",
      longitude: "",
    address:"",
     latitude: "",
    trails: [], isLoaded: false
  }




  handleChange = address => {
   this.setState({
      address

    });

        geocodeByAddress(address)
            .then(res => getLatLng(res[0]))
      .then(({ lat, lng }) => {
    this.setState({

      latitude: lat,
      longitude: lng,

    });
  })
 .catch(error => {
        this.setState({ isGeocoding: false });
        console.log('error', error); // eslint-disable-line no-console
      });

 }

  getUser = selected => {

var object = this.refs.Progress2;

object.innerHTML="";


 this.setState({ isGeocoding: true, address: selected });