title: Extending react custom component
body: <p>I have a react component called editPhoto.js it has a onDeleteFile method that I want to override when I extend it. The problem is editPhoto.js is connected to a redux store. Is inheritance the wrong approach here ? Or how would I go about extending and overriding the EditPhoto onDeleteFile and save methods ?</p>
  
  <p><strong>UPDATE:</strong> 11-1</p>
  
  <p><strong>editPhoto.js</strong> does all the same functionality that editBlog needs to do. So in OOP terms this is a classic case for inheritance by extending editPhoto with editBlog so editBlog inherits all of editPhoto's functions and properties. With inheritance I could also override two methods that editBlog uses differently from editPhoto. The <strong>save</strong> and <strong>onDeleteFile</strong> functions.</p>
  
  <p>Here is how both those functions are used differently.</p>
  
  <p><strong>save() method should call a different action:</strong></p>
  
  <pre><code>save(){
  
     all the same (save) method code in editPhoto goes here....
  
     // this.props.editPhoto(formData, this.props.history) should be changed to
     this.props.editBlog(formData, this.props.history).
  
  }
  </code></pre>
  
  <p><strong>onDeleteFile() method should call a different action:</strong></p>
  
  <pre><code>onDeleteFile(){
  
     all the same (onDeleteFile) method code in editPhoto goes here....
  
     // this.props.editBlog(this.state.id, this.props.history) should be changed to
     this.props.deletePhoto(this.state.id, this.props.history)
  
  }
  </code></pre>
  
  <p>Thats the only two changes in the code which seems crazy to have to duplicate 112 lines of code for just 2 lines to be changed.
  Id' also like to know how you would override a method using composition but its not necessary in this case (maybe best for another post).  </p>
  
  <p>If there is a way of doing this with composition I'm totally open to not using inheritance as it wont inherit when using the Redux connect in EditPhoto.</p>
  
  <p>END OF UPDATE 11-1 -------------------------------</p>
  
  <p>See all code below trying to do the same thing in inheritance.</p>
  
  <pre><code>import React, {Component} from 'react';
  import EditPhoto from './editPhoto';
  
  export default class EditBlog extends EditPhoto{
  
    constructor(props){
      super(props);
    }
  
    // override original EditPhoto
    onDeleteFile(event){
      event.preventDefault();
      console.log("DeleteBlog : onDeleteFile");
      this.props.deleteBlog(this.state.id, this.props.history)
    }
  
   save( event ){
     event.preventDefault();
     const formData .....
     // call different action for editBlog(formData, this.props.history);
   }
  
  } 
  </code></pre>
  
  <p>Here is my editPhoto.js code</p>
  
  <pre><code>import React, {Component} from 'react';
  import {connect} from 'react-redux';
  import Dropzone from 'react-dropzone';
  import FieldEditor from '../../components/admin/fieldEditor';
  import DropzoneArea from '../../components/admin/dropzoneArea';
  import {editPhoto, deletePhoto} from '../../actions/index';
  
  import style from '../../../styles/admin/editPhoto.scss';
  
  class EditPhoto extends Component{
  
    constructor(props){
      super(props);
      this.onUpdateState = this.onUpdateState.bind(this);
      this.handleDrop = this.handleDrop.bind(this);
      this.save = this.save.bind(this);
      this.onDeleteFile = this.onDeleteFile.bind(this);
  
      this.state = {
        fieldEdits:'',
        preview:'',
        file:'',
        id:''
      }
    }
  
    componentWillMount(){
      if(this.props.location.state)
      this.setState({
        preview: this.props.location.state.photo.photo,
        fieldEdits: this.props.location.state.photo,
        id: this.props.location.state.photo._id
      })
    }
  
    onUpdateState(fieldEdits){
      this.setState({fieldEdits});
    }
  
    handleDrop(acceptedFiles, rejectedFiles){
      acceptedFiles.forEach( (file, index) =&gt; {
         const reader = new FileReader();
         reader.onload = ( event ) =&gt; {
            const img = event.target.result;
            this.setState({preview:img, file});
         };
         reader.onabort = () =&gt; console.log('file reading was aborted');
         reader.onerror = () =&gt; console.log('file reading has failed');
  
        reader.readAsDataURL(file);
     });
    }
  
    onDeleteFile(event){
      event.preventDefault();
      this.props.deletePhoto(this.state.id, this.props.history);
    }
  
    save( event ){
      event.preventDefault();
      var form = document.forms.namedItem("photoEditUpload");
      var formData = new FormData(form);
  
      if(this.state.file.name){
        formData.append('photos', this.state.file, this.state.file.name);
      }
  
      formData.append('id', this.state.id);
  
      // for (var pair of formData.entries()) {
      //     console.log(pair[0]+ ' = ' + pair[1]);
      // }
  
      this.props.editPhoto(formData, this.props.history);
    }
  
    render(){
      if(!this.props.location.state){
        // TO DO : ADD IN A ERROR COMPONENT FOR THIS.
        return &lt;div&gt;No photo to edit. GO BACK !&lt;/div&gt;
      }
      return(
        &lt;div id="edit-photo" className='container'&gt;
          &lt;form onSubmit={this.save} ref='form' role="save" encType="multipart/form-data" name="photoEditUpload" method="post"&gt;
            &lt;div className="row"&gt;
              &lt;div className="photo-container col-sm-8"&gt;
                &lt;img src={this.state.preview} className="edit-photo"&gt;&lt;/img&gt;
              &lt;/div&gt;
              &lt;div className="col-sm-4"&gt;
                &lt;div&gt;
                  &lt;Dropzone onDrop={this.handleDrop} multiple={false} accept="image/jpeg" className="dropzone"&gt;
                    &lt;DropzoneArea /&gt;
                  &lt;/Dropzone&gt;
                &lt;/div&gt;
                &lt;div className="delete-container"&gt;
                  &lt;button onClick={this.onDeleteFile} className='btn btn-primary' type='button'&gt;Delete&lt;/button&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
            &lt;FieldEditor callback={this.onUpdateState} {...this.state.fieldEdits} /&gt;
            &lt;div className="button-container"&gt;
              &lt;button className='btn btn-primary btn-save' type='submit'&gt;Save&lt;/button&gt;
            &lt;/div&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      )
    }
  }
  
  export default connect(null, {editPhoto, deletePhoto})(EditPhoto);
  </code></pre>
  
  <hr>
  
  <p><strong>NOTE:</strong>
  Here is a stripped down version in jsfiddle showing the issue after palsrealm suggested passing the context so the store would not be undefined. 
  <a href="https://jsfiddle.net/chapster11/jzprkx96/31/" rel="nofollow noreferrer">https://jsfiddle.net/chapster11/jzprkx96/31/</a></p>