I have a react/django app. In my app.js, I am testing out the ability to pull & render JSONs from my API, but at the same time be able to render react components. My app.js consists of an App class component that refers to Navbar and Navitems that are function components. I also refer to icons that I have saved as word.svg in an icons folder. I am going to include the error messages in dev tools, code for arrow.svg in icon folder, and my App.js folder.
Error:
Target container is not a DOM element.
React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Each child in a list should have a unique “key” prop
Element type is invlaid: react-dom.development.js expected a string or class/function but got: undefined
Check the render method of app
The above error occurred in the <a> componenet
App.js
import { render } from "react-dom";
import './index.css';
import { ReactComponent as BellIcon } from './icons/bell.svg';
import { ReactComponent as MessengerIcon } from './icons/messenger.svg';
import { ReactComponent as CaretIcon } from './icons/caret.svg';
import { ReactComponent as PlusIcon } from './icons/plus.svg';
import { ReactComponent as CogIcon } from './icons/cog.svg';
import { ReactComponent as ChevronIcon } from './icons/chevron.svg';
import { ReactComponent as ArrowIcon } from './icons/arrow.svg';
import { ReactComponent as BoltIcon } from './icons/bolt.svg';
import React, { useState, useEffect, useRef, Component } from 'react';
import { CSSTransition } from 'react-transition-group';
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
loaded: false,
placeholder: "Loading"
};
}
componentDidMount() {
fetch("api/lead")
.then(response => {
if (response.status > 400) {
return this.setState(() => {
return { placeholder: "Something went wrong!" };
});
}
return response.json();
})
.then(data => {
this.setState(() => {
return {
data,
loaded: true
};
});
});
}
render() {
return (
<ul>
{this.state.data.map(contact => {
return (
<div>'
<Navbar>
<NavItem icon={<PlusIcon />} />
<NavItem icon={<BellIcon />} />
<NavItem icon={<MessengerIcon />} />
<NavItem icon={<CaretIcon />}>
<DropdownMenu></DropdownMenu>
</NavItem>
</Navbar>
<li key={contact.id}>
{contact.name} - {contact.email}
<h1>Hi</h1>
</li>
</div>
);
})}
</ul>
);
}
}
function Navbar(props) {
return (
<nav className="navbar">
<ul className="navbar-nav">{props.children}</ul>
</nav>
);
}
function NavItem(props) {
const [open, setOpen] = useState(false);
return (
<li className="nav-item">
<a href="#" className="icon-button" onClick={() => setOpen(!open)}>
{props.icon}
</a>
{open && props.children}
</li>
);
}
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState('main');
const [menuHeight, setMenuHeight] = useState(null);
const dropdownRef = useRef(null);
useEffect(() => {
setMenuHeight(dropdownRef.current?.firstChild.offsetHeight)
}, [])
function calcHeight(el) {
const height = el.offsetHeight;
setMenuHeight(height);
}
function DropdownItem(props) {
return (
<a href="#" className="menu-item" onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}>
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</a>
);
}
return (
<div className="dropdown" style={{ height: menuHeight }} ref={dropdownRef}>
<CSSTransition
in={activeMenu === 'main'}
timeout={500}
classNames="menu-primary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem>My Profile</DropdownItem>
<DropdownItem
leftIcon={<CogIcon />}
rightIcon={<ChevronIcon />}
goToMenu="settings">
Settings
</DropdownItem>
<DropdownItem
leftIcon="🦧"
rightIcon={<ChevronIcon />}
goToMenu="animals">
Animals
</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'settings'}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
<h2>My Tutorial</h2>
</DropdownItem>
<DropdownItem leftIcon={<BoltIcon />}>HTML</DropdownItem>
<DropdownItem leftIcon={<BoltIcon />}>CSS</DropdownItem>
<DropdownItem leftIcon={<BoltIcon />}>JavaScript</DropdownItem>
<DropdownItem leftIcon={<BoltIcon />}>Awesome!</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'animals'}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
<h2>Animals</h2>
</DropdownItem>
<DropdownItem leftIcon="🦘">Kangaroo</DropdownItem>
<DropdownItem leftIcon="🐸">Frog</DropdownItem>
<DropdownItem leftIcon="🦋">Horse?</DropdownItem>
<DropdownItem leftIcon="🦔">Hedgehog</DropdownItem>
</div>
</CSSTransition>
</div>
);
}
export default App;
const container = document.getElementById("app");
render(<App />, container);
arrow.svg
<svg viewBox="0 0 448 512">
<path fill="currentColor" d="M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z" class=""/>
</svg>
Specify key attribute for the enclosing div. Key in li element is redundant:
{this.state.data.map((contact, index) => {
return (
<div key={contact.id}>'
<Navbar>
<NavItem icon={<PlusIcon />} />
<NavItem icon={<BellIcon />} />
<NavItem icon={<MessengerIcon />} />
<NavItem icon={<CaretIcon />}>
<DropdownMenu></DropdownMenu>
</NavItem>
</Navbar>
<li>
{contact.name} - {contact.email}
<h1>Hi</h1>
</li>
</div>
);
})}