Sean Barker
Sean Barker

Reputation: 351

conditionally render child component following onChange event

I'm trying to communicate with a child component, but only following a onChange event in an <input> html element. Can anyone explain to me why the two components dont seem to be communicating, and why the console.log in the child component isnt showing?

PARENT

import React from 'react';
import FileUpload from './FileUpload'


class App extends React.Component {

    callChild = ()=>{

        return (
            <FileUpload displayOnUpload = {this.displayOnUpload} test = 'passed succesfully'/>  

        )   

    }

    render(){

        return ( 
            <div>

                <input 
                    type="file"
                    id = "my-file"
                    multiple 
                    onChange = {()=>this.callChild()} 
                />                                    


            </div>

        )
    }

}

export default App

CHILD

const FileUpload =  (props)=> {
        console.log(props.test)


    return (
        <div>
            hi
        </div>
    )

}

export default FileUpload

Upvotes: 0

Views: 650

Answers (2)

Michiel Dral
Michiel Dral

Reputation: 4074

The way you imagine the React events to work, doesn't work in React, sorry :(

In React, to render something conditionally, the condition must "be inside render", and must depend on either the state, or the props provided to the component.

We only need to change the parent component, you could try:

import React from "react";
import FileUpload from "./FileUpload";

class App extends React.Component {
  // Because we need the App component to "change itself",
  // we add the variable the condition is based on to the state.
  // (in this case, if a file has been selected)
  state = {
    selected_file: null
  };

  render() {
    return (
      <div>
        <div>Hey</div>
        <input
          type="file"
          id="my-file"
          multiple
          onChange={event => {
            // When the event happens, update the state with the file from the input
            this.setState({
              selected_file: event.target.files[0]
            });
          }}
        />

        {/* Only if the file != null (so a file is selected) do we render */}
        {this.state.selected_file != null && (
          <FileUpload
            // I didn't know where `this.displayOnUpload` should come from, so I commented it out
            //displayOnUpload={this.displayOnUpload}
            test="passed succesfully"
            // Pass the file to the child component, so it can use it
            file={this.state.selected_file}
          />
        )}
      </div>
    );
  }
}

export default App;

I hope the comments give you some idea how it works :)

If not, I would start with a React course, as React state is a though concept to grasp when you are starting out. I couldn't teach you that well enough in a Stack Overflow post!

Upvotes: 1

The onChange will call a method (function) but will not render anything. You can use the state to render the component conditionally.

import React from 'react';
import FileUpload from './FileUpload'


class App extends React.Component {

    state = {
        fileChanged = false
    }

    callChild = ()=>{
        this.setState({ fileChanged: true })
    }

    render(){

        if (this.state.fileChanged) {
            return <FileUpload displayOnUpload = {this.displayOnUpload} test = 'passed succesfully'/>
        }

        return ( 
            <div>

                <input 
                    type="file"
                    id = "my-file"
                    multiple 
                    onChange = {()=>this.callChild()} 
                />                                    


            </div>

        )
    }

}

export default App

Upvotes: 1

Related Questions