How to export a function from within a Component class?

In React I am trying to export a function separately from a component class but I am getting this error:

./src/App.jsAttempted import error: 'movieLength' is not exported from './components/movies'.

Here’s the component from which I am trying to export the movieLength() function:

class Movies extends React.Component {
	state = {
		movies: getMovies()
	}

	constructor(props) {
		super(props);

		this.deleteMovie = this.deleteMovie.bind(this);
	}


deleteMovie(movie) {
	const newMovies = this.state.movies.filter((item) => {
		return item._id !== movie._id;
	})

	this.setState({movies: newMovies});
};

export function movieLength() {
	return this.state.movies.length;
}

And here’s the file where I am trying to import it and declare it in a state:

import React, { Component } from 'react';
//import logo from './logo.svg';
import './App.css';
import Movies from './components/movies';
import {movieLength} from './components/movies';

class App extends Component {
state = {
    movieCount: movieLength()
  }

  render() {
    return (
      <main className="container">
      <h2>There are {this.state.movieCount} Movies in this Table!</h2>
      <Movies />
      </main>
    );
  }
}

export default App;

It says the function is not exported but it is actually exported. How to fix this?

Two things:

  1. you’re trying to pass things the wrong way, and
  2. classes don’t work like that (not just in React, or even JavaScript in general)

2 first: a class is just a blueprint for an object. The class create an instance of an object: this

export function movieLength() {
	return this.state.movies.length;
}

Won’t work, because it’s not part of the class: there is no state.movies property outside of a single instance of Movies, you have to have that as a method on the class. At which point it will, while you are in an instance of that Movies object, return the length of the movies array.

But 1 then becomes an issue. If you need to access some state in a sibling, generally that means what you need is to move that state up a level so that it is available to both the components, and pass it down to them as props.

As an example (I’ve just shoved the Movies in a list):

class App extends React.Component {
  deleteMovie = (movie) => {
    const movies = this.state.movies.filter((item) => item._id !== movie._id);
    this.setState({movies});
  };

  state = {
    movies: [],
    deleteMovie: this.deleteMovie.bind(this)
  }

  
  render () {
    return (
      <main className="container">
        <h2>There are {this.state.movies.length} Movies in this Table!</h2>
        <Movies movies={this.state.movies} deleteMovie={this.state.deleteMovie} />
      </main>
    ); 
  }
}
class Movies extends React.Component {
  render() {
    return (
      <ul>
        {this.props.movies.map(movie => (
          <li>
            <h1>{movie.title}</h1>
            <button onClick={() => this.props.deleteMovie(movie)} />Delete</button>
          </li>
        )}
      </ul>
    );
  }
}

Now I am super confused. I am new to React so I cannot handle this big of a change in the code.

I solved this by rendering the Paragraph heading in the Movies component instead of App component.

render() {
		const {length} = this.state.movies;
		if (length === 0) {
			return <p>There are currently No movies in the Database</p>
	}
		return (
			<div>
			<p>Now showing {length} movies to you:</p>
			<table className="table">
			  <thead>
			  <tr>
			    <th>Title</th>
			    <th>Genre</th> 
			    <th>Stock</th>
			    <th>Rate</th>
			    <th></th>
			  </tr>
			  </thead>
			  <tbody>
				{this.state.movies.map((movie) => (
				<tr key={movie._id}>
				<td>{movie.title}</td>
				<td>{movie.genre.name}</td>
				<td>{movie.numberInStock}</td>
				<td>{movie.dailyRentalRate}</td>
				<td><button onClick={() => this.deleteMovie(movie)} id="delete" className="btn-danger">Delete</button></td>
			</tr>
			))}
			  </tbody>
			</table>
			</div>
			);
	}