Get new HOC state in child component after updating HOC parent state in child component

33 Views Asked by At

Given I have a HOC component wrapping a child component. Here is my HOC component:

import React, { Component } from 'react'
import { Put } from '../../../utils/axios'

const HOC = ( WrappedComponent ) => {
  class WithHOC extends Component {
    state = {
      loading: false,      
      userPhoto: {
        id: '',
        content: '',
      }
    }

    load = param => this.setState({ loading: param })    

    onChangeUserPhotoHOC = ( key, val ) => {
      this.setState({ [ key ]: val }, () => {
        console.log(this.state)
      })   
    }  

    updateUserPhoto = ( data ) => {          
      Put(
        `users/${ data.id }/upload_user_photo`,
        data,
        this.updateUserPhotoSuccess,
        this.updateUserPhotoError,
        this.load
      )
    } 
    updateUserPhotoSuccess = () => {
      console.log('success')
    }
    updateUserPhotoError = () => {
      console.log('error')
    }

    render = () => {
      return (
        <>
          <WrappedComponent
            { ...this.props }
            userPhoto={ this.state.userPhoto }
            onChangeUserPhotoHOC={ this.onChangeUserPhotoHOC }
            updateUserPhoto={ this.updateUserPhoto }
          />          
        </>
      )
    }
  }
  return WithHOC
}

export default HOC

And here is my child component which is responsible to take an image and convert it to base64 string.

import React from 'react'
import Filepond from '../../components/Filepond'
import { compose } from 'redux'
import _ from 'lodash'

import WithUserPhotoUploader from './actions'

const UserPhotoUploader = ({
  onChangeUserPhotoHOC,
  updateUserPhoto,
  userPhoto,
  user,
}) => {
  const updateUserPhotoData = ( key, val ) => {    
    if ( !_.isEmpty( userPhoto ) ) {
      let tmp = _.cloneDeep( userPhoto )
      tmp[ key ] = val
      tmp[ 'id' ] = user.id          
      onChangeUserPhotoHOC( 'userPhoto', tmp )      
    }    
  }

  const getBase64String = async ( items ) => {   
    if ( items && !_.isEmpty( items ) ) { 
      let item = items[ 0 ]      
      return 'a random base 64 string'      
    }
    return ''
  }
  
  return (    
    <Filepond 
      onupdatefiles={ async (items) => {
        let item = await getBase64String( items )
        await updateUserPhotoData( 'content', item )
        console.log(userPhoto)
        updateUserPhoto( userPhoto )                  
      }} />
  )
}

export default compose(
  WithUserPhotoUploader
)( UserPhotoUploader ) 

When I drop a file in the filepond component, updateUserPhotoData is called which calls the onChangeUserPhotoHOC which updates the state of the HOC component.

My question is, why wouldnt userPhoto props in the child component be updated with the new state when I drop a file? Its still showing:

{
   userId: '',
   content: '',
}

even though the HOC component state is updated. Am I missing something?

Edit 1

I tried this but it doesnt work..

return ( 
    <>      
      <Filepond         
        onaddfile={ items => {
          let item = getBase64String( items )   
          let tmp = _.cloneDeep( userPhoto ) 
          tmp[ 'content' ] = item   
          console.log(tmp)            
          Promise.all([
            onChangeUserPhotoHOC( 'userPhoto', tmp )
          ]).then(() => {
            console.log(userPhoto)
          })                        
        }}/>      
    </> 
  )  

What im trying to achieve is get the state updated first then do something with it after. I dont want to use a callback function after setting state as I prefer to call the action outside independently

0

There are 0 best solutions below