3

I read a bit about answers but haven't found something that's what I'm looking for. Please refer me to a relevant question and delete my question if it's after all a duplicate.

I've got the following file structures:

As seen in the code, I have in CoinsTable an array of objects called supportedCoins, whose elements are CryptoCoin objects, and those have the property iconURL which stores the path of images (which are icons).

As seen in the code, in Coinstable.js I have code that renders a table that displays all the elements of supportedCoins, each property separately, using their object properties (e.g supportedCoins['bitcoin'].symbol), but when trying to render the following for a CryptoCoin, for example, again with supportedCoins['bitcoin']: <img src={supportedCoins['bitcoin'].iconURL, the rendered src is the actual path, but React doesn't render the picture.

That's what I want to do and what I want for to work.

What I found out that does work is doing the following to do in CoinsTable.js:

  1. Import the icon from the right path, for example: import biticonURL from './coins_icons/bitcoin_icon.png - same path as the one in supportedCoins['bitcoin'].iconURL`

  2. Create an image as desired, only with src={biticonURL}: `

To compare the different things I tried, here are the resulted srcs of supportedCoins['bitcoin']: - With supportedCoins['bitcoin'].iconURL: ./coins_icons///bitcoin_icon.png - With bitcoinIcon(import): /static/media/bitcoin_icon.b6168699.png

Why am I getting wrong paths, and why does store my pictures there? The images aren't stored on my server in those paths.

Jules Dupont
  • 7,259
  • 7
  • 39
  • 39
Gal Grünfeld
  • 800
  • 3
  • 9
  • 32

1 Answers1

1

Why am I getting wrong paths with triple forward slashes?

You're getting the ./coins_icons///bitcoin_icon.png path because of how you concatenate strings in CoinsList.js. Here's the relevant code:

const coinsIconsDir = './coins_icons/';
supportedCoins['bitcoin'] = new CryptoCoin ('BTC', 'Bitcoin', coinsIconsDir + '/' + '/bitcoin_icon.png');

Notice that there is one forward slash at the end of coinsIconsDir, one as a single character, and one at the beginning of '/bitcoin_icon.png', which is why you're getting that triple slash. The simplest way to fix that is to just pick one consistent place for the forward slash, like the following for example:

const coinsIconsDir = './coins_icons';
supportedCoins['bitcoin'] = new CryptoCoin ('BTC', 'Bitcoin', `${coinsIconsDir}/bitcoin_icon.png`);

Now your path will be ./coins_icons/bitcoin_icon.png as desired.

Why are my pictures stored under the static/media/ path?

You're using a build and bundle system to run your app. That system is taking the resources you are importing and storing them under the static/media/ folder before running your web app. Based on the static/media/ path, I'm guessing that you're using create-react-app, which will take images and other static assets and place them in a static folder in the final build. That's described here in the documentation. The most relevant lines are

Webpack finds all relative module references in CSS (they start with ./) and replaces them with the final paths from the compiled bundle.

This ensures that when the project is built, Webpack will correctly move the images into the build folder, and provide us with correct paths.

So what does that mean for your case?

I'm going to give you a number of alternatives for importing images and you can pick the one you like best.

If you fix the forward slashes, you should be able to use:

<img src={supportedCoins['bitcoin'].iconURL} style={{maxHeight:'25px'}}/>

However, if ./coins_icons/bitcoin_icon.png is not publicly available on your server (which is probably the case if you're using create-react-app), this will not work.

In that case, you'll either need to put the image somewhere that's publicly available (in create-react-app that's the public folder), or continue to import them as you are doing. There are several different ways to import, including using the syntax you currently have:

import bitcoinIcon from './coins_icons/bitcoin_icon.png';

If you're using Webpack, you can also use require. Note that require needs at least some file path information, so you'll need to do the file path construction inside the require.

// Assuming supportedCoins['bitcoin'].iconName has been initialized to the icon's file name
// e.g., supportedCoins['bitcoin'].iconName === bitcoin_icon.png
<img src={require(`./coins_icons/${supportedCoins['bitcoin'].iconName}`)} style={{maxHeight:'25px'}}/>

However, requires outside of the top level and dynamic requires can be considered bad practice. To avoid that you could change CoinsList.js to:

import bitcoinIcon from './coins_icons/bitcoin_icon.png';
import ethereumIcon from './coins_icons/ethereum_icon.png';
import dashIcon from './coins_icons/dash_icon.png';
import iotaIcon from './coins_icons/iota_icon.png';

var supportedCoins = new Array();
const coinsIconsDir = './coins_icons/';
supportedCoins['bitcoin'] = new CryptoCoin ('BTC', 'Bitcoin', bitcoinIcon);
supportedCoins['ethereum'] = new CryptoCoin('ETH', 'Ethereum', ethereumIcon);
supportedCoins['dash'] = new CryptoCoin('DASH', 'Dash', dashIcon);
supportedCoins['iota'] = new CryptoCoin('IOTA', 'IOTA', iotaIcon);

and then in CoinsTable.js do:

<img src={supportedCoins['bitcoin'].iconURL} style={{maxHeight:'25px'}}/>

I'd pick this last option because it keeps the coin definition contained inside one file and keeps all imports static.

Jules Dupont
  • 7,259
  • 7
  • 39
  • 39
  • Your analysis and guessing were spot-on! I did use `react-create-app`. :) The `require()` option didn't work for me. I got an error when I used it: `Error: Cannot find module "."` Shouldn't it have worked if I used `react-create-app`? – Gal Grünfeld Dec 27 '17 at 01:14
  • Ah shoot, you're right. I tested the webpack `require` with a string literal but not a variable, and variables do not work as noted [here](https://stackoverflow.com/questions/42797313/webpack-dynamic-module-loader-by-require). Give me a minute to update my answer. – Jules Dupont Dec 27 '17 at 02:04
  • Putting the `coinsIcons` folder in the `public` folder and then just giving paths: `/coinsIcons.whateverIcon` worked like a charm! So thanks so very much! I've been stuck on this. But I'm not going to accept your answer just yet, as I want to webpack to take care of this for me, along with all the other files, and your solution doesn't provide that. – Gal Grünfeld Dec 27 '17 at 02:21
  • As far as I am aware, your choices are placing the images in the `public` folder or handling the imports yourself as shown above. If you find a better solution please let me know. Happy coding! – Jules Dupont Dec 27 '17 at 02:35
  • Alright, I'll accept your answer and create a post about Webpack specifically. Thanks a lot! It works fully with your solution. :) – Gal Grünfeld Dec 27 '17 at 02:36
  • If you make another question make sure to specify that you're using `create-react-app` because that affects the Webpack features you have access to. Good luck! – Jules Dupont Dec 27 '17 at 03:31