CeriW
December 18, 2023, 5:00pm
1
Hi guys,
I’ve created a few different apps using create-react-app. I am able to get them to run locally, but I am completely failing to get them to deploy to Netlify properly. All I get is a blank page with a #root element.
Here is an example of one such site: https://tangerine-elf-b2236d.netlify.app/
Here is the Github repository for it: GitHub - CeriW/pokediscoverer: Display information about pokemon in the user's web browser
I’ve googled and have tried everything I’ve come across but I don’t seem able to make it work. Can anyone help?
CeriW
December 18, 2023, 8:36pm
3
This is all that’s in my index.tsx - it was pretty much what create-react-app created for me:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Here’s my app component:
export default function App() {
const [pokemon, setPokemon] = useState<Pokemon | null>(samplePokemon);
const [heldItems, setHeldItems] = useState<{ name: string; sprite: string }[]>([]);
const [mainTheme, setMainTheme] = useState('default');
const [subTheme, setSubTheme] = useState('default');
const date = new Date();
const pokemonOfTheDayId = date.getDay() + 1 * date.getDate() * Math.ceil(date.getMonth() / 3) + 1;
const fetchNewPokemon = async (id?: number | string) => {
if (pokemon.id !== id) {
try {
const newPokemon = await getNewPokemon(id);
setPokemon(newPokemon);
} catch (error) {
console.error('Error:', error);
}
}
};
useEffect(() => {
setMainTheme(pokemon.types[0].type.name);
const subTheme = pokemon.types[1] ? pokemon.types[1].type.name : pokemon.types[0].type.name;
setSubTheme(subTheme);
}, [pokemon]);
useEffect(() => {
setHeldItems([]);
if (pokemon) {
const newHeldItemsPromises = pokemon.held_items.map(async (item) => {
const itemInfo = await getHeldItem(item.item.url);
return itemInfo;
});
Promise.all(newHeldItemsPromises)
.then((resolvedHeldItems) => {
setHeldItems(resolvedHeldItems);
})
.catch((error) => {
console.error('Error fetching held items:', error);
});
}
}, [pokemon]);
const themeClassName = `${mainTheme} sub-theme-${subTheme}`;
return (
<div id="app" className={themeClassName}>
<h1>PokéDiscoverer</h1>
<div className="button-panel">
<div>
<button
onClick={(e) => {
fetchNewPokemon();
const thisButton = e.currentTarget;
thisButton.disabled = true;
setTimeout(() => {
thisButton.disabled = false;
}, 1500);
}}
data-testid="random-pokemon-btn"
>
Give me a random pokemon
</button>
<button
onClick={() => {
fetchNewPokemon(pokemonOfTheDayId);
}}
data-testid="pokemon-of-the-day-btn"
>
Pokemon of the day
</button>
</div>
<div className="pokemon-selector">
<Autocomplete
options={pokemonList}
sx={{
width: 200,
}}
value={null}
onChange={(event: any, newValue: string | null) => {
if (newValue) {
fetchNewPokemon(pokemonList.indexOf(newValue) + 1);
event.target.value = null;
}
}}
renderInput={(params) => <TextField {...params} label="Search" variant="standard" />}
/>
</div>
</div>
{pokemon ? (
<div className="pokemon-card" data-testid="pokemon-card">
<div className="pokemon-header">
<h2 className="pokemon-name">{pokemon.name}</h2>
<div className="pokemon-id">#{pokemon.id}</div>
</div>
<div className="pokemon-data">
<div className="pokemon-text">
<TypeList list={pokemon.types} />
<GenerationDisplay id={pokemon.id} />
<div className="pokemon-info">
<WeightList hectograms={pokemon.weight} />
<HeightList decimeters={pokemon.height} />
</div>
<BaseStatList list={pokemon.stats} />
<div className="held-items-container">
<HeldItemsList list={heldItems} />
</div>
</div>
<SpriteList spriteList={pokemon.sprites} />
<img className="main-artwork" src={pokemon.sprites.other['official-artwork']['front_default']} alt="" />
</div>
</div>
) : (
''
)}
<footer>
<div>
<a href="https://github.com/cherrycodesnet/random-pokemon" target="_blank" rel="noreferrer">
About this project
</a>
<div
className="my-fav-pokemon"
onClick={() => {
fetchNewPokemon(2);
}}
>
Developer's favourite pokemon
</div>
</div>
<sub>All info and images are © The Pokemon Company and Nintendo</sub>
</footer>
</div>
);
}
I’m not sure where the problem is? Apologies if it’s obvious, I’m pretty new to React.
@CeriW The response from the previous “user” appears to be an AI powered spam bot response and should be ignored due to being unmitigated garbage.
I’ll step you through your true issue and how to actually fix it.
It’s revealed by looking at the devtools in your browser:
You can see that the files necessary for the page to load correctly aren’t found.
You are serving from the root, which is evidenced by the URL being https://tangerine-elf-b2236d.netlify.app , but in the deployed source you can see these references:
You can confirm the files don’t exist at those locations by trying to access them:
https://tangerine-elf-b2236d.netlify.app/pokediscoverer/favicon.ico
https://tangerine-elf-b2236d.netlify.app/pokediscoverer/static/js/main.04c989dc.js
https://tangerine-elf-b2236d.netlify.app/pokediscoverer/static/css/main.a5f54af9.css
When your npm run build
command is run you’ll find that it says:
It’s expecting that you intend to host the project in a folder of /pokediscoverer/
but have your Publish directory set to build
and thus the files are deployed to the root.
Proven by the files being found here:
https://tangerine-elf-b2236d.netlify.app/favicon.ico
https://tangerine-elf-b2236d.netlify.app/static/js/main.04c989dc.js
https://tangerine-elf-b2236d.netlify.app/css/main.a5f54af9.css
As the build logging explains, you can control how it produces the files by adjusting the homepage
field in your package.json
.
You currently have that value set to:
Which is why it’s producing the file references with the /pokediscoverer/
folder in them.
If you’re serving from the root, you can delete the homepage
declaration in your package.json
and it’ll assume /
.
If you do that, then run a build, you will see:
2 Likes
CeriW
December 19, 2023, 4:32pm
5
Fantastic, thank you so much! Your explanation was very in depth.
I’d previously published this site on Github Pages but wanted to move to Netlify to give me more control over the final URL. This was why the homepage info was in there.
All working now!
SamO
December 19, 2023, 7:52pm
6
glad to hear it’s working now.