Import image using this.props.src in React - javascript

I am giving my component 2 props src and alt so that it could display an image like so:
<img src={require(this.props.src)} alt={this.props.alt} />
Running my app gives me this error
Error: Cannot find module "."
I tried the image URL and it is correct and works, the app just doesn't want to work when I supply require the props.

If you're using webpack, I'm going to assume that you're using the webpack image loader. If that's the case it means that you're importing your images in your component, probably using named imports. In that case you can pass the named import as a prop to either a child component or use it directly on the component where the import lives.
// named import
import landscape from "./img/landscape.jpg";
// child component
import Child from "./components/child";
const Parent = () =>
<div>
<Child src={landscape} />
</div>;
// then the child component could look like this
const Child = (props) =>
<div>
<img src={props.src} />
</div>;
If this is not the case, please give more information regarding how webpack is handling the images in your components.

Related

How to properly use .scss modules with React components

I have a question regarding how to correctly use .scss modules(and common css modules) when it comes to use the same .scss module in several components at once.
For instance: if a parent & its children need to access the same exact .scss module, which way is the best to access the module?
Assume I have a .scss module which contains all styles and a component AudioPlayer that has a structure like this:
import audioPlayerModule from './SCSS/AudioPlayer.module.scss';
/*Some code*/
return (
<div className={audioPlayerModule.audio_container}>
<LeftControls/>
<CenterControls />
<RightControls/>
</div>)
The main AudioPlayer component uses the module audioPlayerModule. Then let's say I need this module again inside the child component LeftControls:
import audioPlayerModule from './SCSS/AudioPlayer.module.scss';
const LeftControls = () => {
return (
<div className={audioPlayerModule.left_controls_container}></div>
);
}
Thus I have imported the same .scss module "audioPlayerModule" to parent & each of its children. Is there any better way to do it without using "props.children"?
You can pass className props to your child components
<LeftControl className={audioPlayerModule.left_controls_container}/>
and then spread this props in child
const LeftControls = ({props}) => {
return (
<div {...props}></div>
);

Is it possible to destructure image folder files in React Component?

I'm creating a react app. I have an image folder with a few files. In order for React to render the image I have to import it like I import other modules. Something like this:
What I want to do is import the whole image folder, and then find a way to access each file in my Component. for example:
import img from '.../img'
In my JSX, I want to be able to access each of the files from the imported image folder.
Is it possible to do?
You still need to import those images in some place. For cleaner syntax in your main component file, I will group the image files in 1 file
//grouping images in one module. Let's say it is image.js
import imageA from <your-patha>
import imageB from <your-pathb>
import imageC from <your-pathc>
export default {
imgA: imageA,
imgB: imageB,
imgC: imageC
}
//Home component
import Images from '<image.js path>'
const Home = () => {
return (
<img src={Images.imgA} //...other props />
)
}
The best way to do this is you can put all your images in the public folder and refer like below on component.
<img src="/image.jpg" alt="image" />

Persist data between two pages with Next.js

I would like to refactor my Next.js webapp to have different pages handle different screens. Currently, I have this component holding several states to know in which screen I'm in. In the jsx section, I'm using {value && ... } to render the right component.
But I feel this is not good design, and won't be maintainable when adding more and more screens.
I would also like to avoid Redux as it is overkill for my project.
I was thinking about persisting data in cookies so I can retrieve them with getInitialProps in every component when rendering a new page, but is there a more elegant way?
I've read about tweaking the _app.js but I'm not sure to understand the consequences of doing so, and how it could help me..
Any suggestion?
When multiple of your pages need to make use of same data, you can make use of Context to store the result. It a good way to make a centralized storage without using complex and more self sufficient libraries like redux
You can implement context inside of _app.js file which must reside inside your root folder. This way next.js treats it as a root wrapper and you would just need to use 1 instance of Context
contexts/appContext
import React from 'react';
const AppContext = React.createContext();
export const AppProvider = AppContext.Provider;
export const AppConsumer = AppContext.Consumer;
export default AppContext;
_app.js
import React from 'react'
import App from 'next/app'
import AppProvider from '../contexts/appContext';
class MyApp extends App {
state={
data:[]
}
render() {
const { Component, pageProps } = this.props;
// You can implement logic in this component to fetch data and update state
return (
<div>
<AppProvider value={this.state.data}> // pass on value to context
<Component {...pageProps} />
</AppProvider>
</div>
)
}
}
export default MyApp
Now further each component can make use of context value by using AppConsumer or using useContext if you use hooks
Please read more about how to use Context here

Image not loading when passing a prop to <img src="this.prop." /> in React

I have an issue regarding a link not loading my image when I pass a prop to the attribute src of img. I have tried wrapping require() around my links and it didn't work.
I have a huge library of products which would be unfeasible to manually import images using the image loader.
Therefore, is there a way to load an image using props inside the src attribute?
I am using NODE_PATH=src/
Thanks for the help!
export const productLib = [{
ID: "001",
name:"product name",
src: "lib/productLib/img/product_name",
color: "",
...
}, {...}]
import React from 'react';
export class Products extends React.Component {
render() {
return(
<div className="products">
<img src={this.props.product.src} width="50" />
<h6>{this.props.product.name}<span className={`block ${this.props.product.color}`}></span></h6>
</div>
)
}
}
As recommended by Xuscrus, I linked my images using the public path. I had to remove my absolute path in order for this solution to work.
I moved all of my images inside a folder named "img" inside the public folder of my create-react-app.
With the example used in my initial statement, here is the easiest solution I found:
import React from 'react';
export class Products extends React.Component {
render() {
return(
<div className="products">
<img src={`/img/${this.props.product.src}.png`} width="50" />
<h6>{this.props.product.name}<span className={`block ${this.props.product.color}`}></span></h6>
</div>
)
}
}
My main reference for my solution was this post (URL method in the correct answer) :
How to do Dynamic images in ReactJS?
I think issue is related with the way you are sending the url to the component.
"lib/productLib/img/product_name" is not an url, not relative url also.
You can use import to get the image.
import React from 'react';
import logo from './logo.png'; // Tell webpack this JS file uses this image
console.log(logo); // /logo.84287d09.png
function Header() {
// Import result is the URL of your image
return <img src={logo} alt="Logo" />;
}
export default Header;
If you are using react-create app
they resolve the problem for you:
https://create-react-app.dev/docs/adding-images-fonts-and-files/
I came across a similar issue in fact I was searching for the solution at the moment but figured it out myself I have Images store in a separate folder and I'm importing them in the data file and then Passing it to the component where I needed it, but the image was not displaying.
All I did was
//img is the variable I'm getting the image path at
console.log(img)
That returned
Module {default: "/static/media/svg-1.af890272.svg", __esModule: true,
Symbol(Symbol.toStringTag): "Module"}
default: "/static/media/svg-1.af890272.svg"
Symbol(Symbol.toStringTag): "Module"
__esModule: true
[[Prototype]]: Object
After Getting this in the Module Object I saw the default value so just do
img = img.default
And now you can pass it in src
import React from 'react';
<img src={img} width="50" />

Is it possible to unload dynamic css imports in react?

I have two files which i load with react.lazy and suspense:
import React, { Suspense, lazy } from "react";
import { Route, Redirect } from 'react-router-dom';
const MainLayout = lazy(() => import('Components/Layout/MainLayout'))
export const PrivateRoute = () => (
<Route render={() => {
return (
localStorage.getItem('user') != null// validation that it is a valid user
?
<Suspense fallback={<div>Loading...</div>}>
<MainLayout/>
</Suspense>
: <Redirect to={{ pathname: '/login'}} />)
}} />
)
Second:
import React, { Suspense, lazy } from "react";
const DefaultLayout = lazy(() => import('Components/Layout/DefaultLayout'))
export const PublicRoute = () => (
<Suspense fallback={<div>Loading...</div>}>
<DefaultLayout/>
</Suspense>
)
the /login path is refrencing a component (login) that is inside of the
DefaultLayout component.
Scenario:
When the user is not logged in I load the DefaultLayout component which in turn contains my login component which imports cssFile1.css.
When the user enters the credentials i forward them to a path that is contained in my PrivateRoute where in turn i have cssFile2.css
The problem here is that cssFile1.css was loaded when i was using the loginpage but when the user logs in i want to unload cssFile1.css, is this possible and if yes then how?
I found a (sort of) reasonable way to do this in React. In short, you can lazy-load React components that contain the import './style.css', and when it loads, you can capture the imported StyleSheet to toggle its StyleSheet.disabled property later.
Here's my original solution to this problem.
Here's a Gist.
Ok, This might not be the most optimum approach, but can't the whole CSS inside the cssFile1.cssbe scoped? As in all the rules are written targetting elements if they are inside a certain container with a class say 'cssFile1'.
Likewise the 2nd CSS file will target all the elements only if they are located inside a container with the class 'cssFile2'.
now all you have to do to "unload/switch" the css is changing the main container class and the respective CSS rules will apply.
One last tip is, if you are using SASS / LESS its just a matter of enclosing the rules inside a container and all the rules will be scoped upon compilation.
If I understand right, then no, it's impossible, because of Webpack imported css when React compiled, anyway, you can try to css in js libs, such a Aphrodite.

Categories

Resources