I have a folder structure with a lot of images and I have a script that compiles the relative paths to an index file during the build, which I then could reference in the code programatically.
Currently, these index files look like this and sit alongside the images:
import file0 from "./IMG_6126.jpg";
import file0min from "./IMG_6126MIN.jpg";
import file1 from "./IMG_6139.jpg";
import file1min from "./IMG_6139MIN.jpg";
export const LPP_2022_07_09 = [
{
url: file0,
minUrl: file0min,
height: 3407,
width: 6000,
dateTaken: new Date(),
},
{
url: file1,
minUrl: file1min,
height: 4000,
width: 5281,
dateTaken: new Date(),
}
];
I can then use the index file like this
import { LPP_2022_07_09 } from "../Collections/London/LPP 2022-07-09";
export const Album = () =>
LPP_2022_07_09.map((i) => <img src={i.minUrl} />);
However, this makes a request for every image see here regardless if it's used in the current component tree or not.
This already takes more than a second to parse through just running locally. The request response is just `export default //url//'. I tried using default exports but the same thing happened. What is going on here?
Related
current directory setup:
- components
- NavBar
- Header
- Layout
- pages
- pages
- demo.js
- _app.js
- index.js
// index.js
import React from 'react';
import NewLayout from "../../components/NewLayout/NewLayout.js";
import $nacelle from '../../services/nacelle';
const Index = ({page}) => (
<>
<NewLayout header={page} />
<pre>{JSON.stringify(page.id, null, 2)}</pre>
</>
);
export async function getStaticProps({ context }) {
try {
const page = await $nacelle.data.content({
handle: 'header_us_retail',
type: 'header'
});
return {
props: { page }
};
} catch {
// do something useful if it doesnt work
const page = 'failed';
return {
props: { page }
};
}
}
export default Index;
I am importing Layout into the index.js file, loading asynchronous data and passing it to layout as props that will then be used to render the header and navbar (which are imported by the layout component). This works as expected in the index file, however I want this same functionality to work in the demo.js file and any other file I create in pages or elsewhere. Most likely the issue is how I'm trying to use Nextjs and React (new to both), any help would be greatly appreciated.
Turns out the issue was with how Nacelle was accessing the environment variables, so not a NextJS, or React issue.
According to the devs there are multiple ways to expose the environment variables and the following method solved my particular issue:
// file in root: next.config.js
module.exports = {
env: {
NACELLE_SPACE_ID: process.env.NACELLE_SPACE_ID,
NACELLE_GRAPHQL_TOKEN: process.env.NACELLE_GRAPHQL_TOKEN,
NACELLE_ENDPOINT: process.env.NACELLE_ENDPOINT,
},
};
This is my first sample table using react-data-grid, columns are not rendered next to each other, instead they are overlapping over and over each other
Below is the very basic sample code I am trying. The code renders the table with data but renders the columns and data on top of each other like this:
Output:
ID
Title
1
Task
2
Task
import React from 'react';
import DataGrid from 'react-data-grid';
export default class extends React.Component {
constructor(props, context) {
super(props, context);
this._columns = [
{
key: 'id',
name: 'ID',
resizable: true,
width: 40
},
{
key: 'task',
name: 'Title',
resizable: true
}
];
this.createRows();
this.state = null;
}
createRows = () => {
const rows = [];
for (let i = 1; i <= 2; i++) {
rows.push({
id: i,
task: 'Task'
});
}
this._rows = rows;
};
rowGetter = (i) => {
return this._rows[i];
};
render() {
return (
<DataGrid
columns={this._columns}
rowGetter={this.rowGetter}
rowsCount={this._rows.length}
minHeight={500}
minColumnWidth={120}
/>
);
}
}
This is because the css is not working.
Here is the quick solution which worked for me:
Go to path in explorer <project-name>\node_modules\react-data-grid\dist and open the react-data-grid.css file.
Copy complete css code and paste it inside your <project-name>\src\App.css file.
Refresh URL. (optional)
This worked for me.
You need to import the CSS of react-data-grid. Usually it is located in the folder :
node_modules\react-data-grid\dist. Find the actual location of this CSS file after you installed the package.
If the CSS file is located in the folder I mention, just import it into your js file :
import React from 'react';
import DataGrid from 'react-data-grid';
import 'react-data-grid/dist/react-data-grid.css';
It should work.
Sam issue here, all my text was appearing on top of each other, even though I could highlight empty grid and navigate through them with the arrow keys.
My solution was similar to Akanksha's but I just copied the entire
node_modules\react-data-grid\dist\react-data-grid.css
file to the same level as my App.css and linked to it directly in the component that is using react-data-grid.
import 'react-data-grid.css';
Hoping that would keep loading size down until its needed and prevent it from causing any odd errors by affecting other classes when I didn't expect it.
I'm trying to create a map component in React using the Tangram Library.
I got it working with Webpack alone but it started bugging out when I used react in the mix.
I've tried using various loaders such as a raw loader, a yaml loader and so forth, but none of them have worked thus far.
The map component looks as follows:
// -- Import dependencies --
import React from 'react';
import { Map } from 'react-leaflet';
// -- Import Tangram --
import Tangram from 'tangram';
import yaml from 'js-yaml';
import data from '!!raw-loader!./scene.yaml';
export default class LeafletMap extends React.Component {
componentDidMount() {
const layer = Tangram.leafletLayer({
scene: data
});
layer.addTo(this.map.leafletElement);
}
render() {
return (
<Map center={[40.70532, -74.00976]} zoom={15} ref={(ref) => { this.map = ref }} />
);
}
}
How can I actually load the scene.yaml so that the Tangram library makes use of it ?
In the end it responds with a 404 as the file isn't found.
The solution was, that the static files weren't being copied to the bundle built by webpack.
I solved it by using the CopyPlugin in the webpack config and copying the files to a folder respecting the relative path name, like so:
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: './bundle.js'
},
plugins: [
new CopyPlugin([
{ from: 'src', to: 'src' },
]),
],
};
I need to customize the way webpack is handling imports in my app.
Some of my services have mock implementations.
In test mode, I want to import mock file instead of real service if a file with ‘.mock’ postfix exists next to the service, otherwise imports the service itself.
Please note that I need different output files (‘main.js’ and ‘test.js’). So I need to make sure test.js is not including the real services implementations (preventing execution is not enough, the source should not be imported at all).
Services folder contains following files:
service-1.js
service-1.mock.js
service-2.js
index.js
services/index.js:
import service1 from ‘./service-1’
import service2 from ‘./service-2’
export {service1, service2}
Please advise how can I config my webpack.
According to the comments I can suggest these workarounds using custom loader:
Method #1
Create one .mobile and .desktop for each of your components along the main file (e.g: component.js, component.mobile.js, component.desktop.js) and use this custom loader:
const targets = {
desktop: 'desktop',
mobile: 'mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header';
import Footer from './shared/about';
import Categories from './category/categories';
// rest of code
`;
const manipulated = manipulateSource(source, targets.mobile, ['components', 'shared']);
console.log(manipulated);
function manipulateSource(src, target = targets.desktop, pathMatches = []) {
const paths = pathMatches.length ? `(${pathMatches.join('|')})` : '';
const pattern = new RegExp(`(?<left>.*import.*${paths}.*\\\/)(?<name>[\\w\\-_]*)(?<rest>.*\\n)`, 'g');
const manipulated = src.replace(pattern, (...args) => {
const [{
left,
name,
rest
}] = args.slice(-1);
return `${left}${name}.${target}${rest}`;
});
return manipulated;
}
Method #2
For those files has different implementations for .mobile and .desktop create the third file (or fourth in case you want to put shareable code in main file) with same name and a meaningful extension (e.g: component.platformAdaptive.js) which can be handled with regular expresion (or any other way of manipulation). In this method you may need to put basic implementation in last file in case you use strongTypes (e.g: Typescript):
const targets = {
desktop: 'desktop',
mobile: 'mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header.platformAdaptive';
import Footer from './shared/about.platformAdaptive';
import Categories from './category/categories.platformAdaptive';
// rest of code
`;
const manipulatedMob = manipulateSource(source, 'platformAdaptive', targets.mobile);
const manipulatedDesk = manipulateSource(source, 'platformAdaptive');
console.log(manipulatedMob);
console.log(manipulatedDesk);
function manipulateSource(src, replace, target = targets.desktop) {
const pattern = new RegExp(`(?<left>.*\\\/)(?<name>[\\w\\-_]*\.)${replace}(?<rest>.*\\n)`, 'g');
const manipulated = src.replace(pattern, (...args) => {
const [{
left,
name,
rest
}] = args.slice(-1);
return `${left}${name}${target}${rest}`;
});
return manipulated;
}
Both of the above methods come with some restrictions in imports, like you can't use Barrel files (index.js) since they assume last chunk of the import is the component file.
In this case you can add multiple folders with a barrel to handle those imports. for example in second method you'll need such structure:
|-- components.platformAdaptive
|-- index.js
|-- components.mobile
|-- index.js
|-- components.desktop
|-- index.js
Or You can use / instead of . to create a nested structure (e.g: components/platformAdaptive):
|-- components
|-- [+] platformAdaptive
|-- [+] mobile
|-- [+] desktop
Method #3
Another way to handle this situation would be to have different classes with different names. For example, a List component with different implementations for mobile and desktop then there would be three components like ListPlatformAdaptive, ListMobile, ListDesktop - in which the ListPlatformAdaptive may has the basic implementations - and a barrel in component folder which exports the components:
import * as ListPlatformAdaptive from './list.platformAdaptive';
import * as ListMobile from './list.mobile';
import * as ListDesktop from './list.desktop';
export {
ListPlatformAdaptive,
ListMobile,
ListDesktop
}
The structure would be like this:
|-- components
|-- list.platformAdaptive.js
|-- list.mobile.js
|-- list.desktop.js
|-- index.js
Then manipulation would be like this:
const targets = {
desktop: 'Desktop',
mobile: 'Mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import HeaderPlatformAdaptive as Header from './shared/Header';
import FooterPlatformAdaptive as Footer from './shared/about';
import CategoriesPlatformAdaptive as Categories from './category/categories';
// rest of code
`;
const replace = 'PlatformAdaptive';
const manipulatedMob = manipulateSource(source, replace, targets.mobile);
const manipulatedDesk = manipulateSource(source, replace);
console.log(manipulatedMob);
console.log(manipulatedDesk);
function manipulateSource(src, replace, target = targets.desktop) {
const pattern = new RegExp(replace, 'g');
const manipulated = src.replace(pattern, target);
return manipulated;
}
I this method you should be careful about the barrel files to be excluded and the downside of this method is that all of the components have been imported already therefore import cost is not acceptable.
Method #4
Another way I can think of is to add some notes as comment and react againts its existance in that line:
const targets = {
desktop: 'Desktop',
mobile: 'Mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header'; /* #adaptive */
import Footer from './shared/about'; /* #adaptive: Desktop */
import Categories from './category/categories'; /* #adaptive: Mobile */
// rest of code
`;
const manipulatedMob = manipulateSource(source, targets.mobile);
const manipulatedDesk = manipulateSource(source);
console.log(manipulatedMob);
console.log(manipulatedDesk);
function manipulateSource(src, targetDevice = targets.desktop) {
const pattern = /(?<left>.*import\s+)(?<name>\w+)(?<rest1>.*)\#adaptive(\:\s*(?<target>\w+))?(?<rest2>.*)/g
const manipulated = src.replace(pattern, (matched, ...args) => {
let [{
left,
name,
rest1,
target,
rest2
}] = args.slice(-1);
target = target || targetDevice;
return target == targetDevice ?
`${left}${name}${target}$ as ${name}${rest1}${rest2}` :
matched;
});
return manipulated;
}
In this method like method #2 imported components names are different than the original but mapped to original name which is not good at all, but I like it the most since if using it in barrel files and it's possible to change imported file address. Another fun part can be to pass target files address with respect to target device and parse it.
Conclusion
As you can see all of my answers were about handle sources without checking the existence of the file and assumes the developer is sure about it. BTW, you can search to see if there is anyway to find file absolute path and then check availability of targeted substitutes.
I am Getting export error in my project .
what's the correct way of exporting ?
And what's the issue with this?
error:
The development server returned response error code: 500
URL:
http://192.168.43.244:8081/index.android.bundle?platform=android&dev=false&hot=false&minify=false
Body:
{"from":"E:\reactNative\chat\awsm\camera\icons.js","to":"../assets/512","message":"Unable
to resolve module ../assets/512 from
E:\\reactNative\\chat\\awsm\\camera\\icons.js: could not resolve
`E:\reactNative\chat\awsm\assets\512' as a folder: it did not
contain a package, nor an index
file","name":"UnableToResolveError","type":"UnableToResolveError","errors":[{}]}
processBundleResult
BundleDownloader.java:172 access$100
BundleDownloader.java:38 execute
BundleDownloader.java:108 emitChunk
MultipartStreamReader.java:69 readAllParts
MultipartStreamReader.java:116 onResponse
BundleDownloader.java:96 execute
RealCall.java:135 run
NamedRunnable.java:32 runWorker
ThreadPoolExecutor.java:1112 run
ThreadPoolExecutor.java:587 run
Thread.java:818
index.js
const globe = require('./globe-icon.png');
const postit = require('./post-it-icon.png');
export { globe,
postit}
icons.js
import { globe,
postit} from '../assets/512'
const icons =[
{ name: 'Notes', image: postit },
{ name: 'Earth', image: globe }
]
export { icons }
I believe your export is fine, but the import is not correct. You need to specify the source of the import. So:
import { globe, postit }
should be replaced with
import { globe, postit } from './whatever'
where './whatever' should be '.' if the files are in the same folder.
The docs — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Looks like the relative path to the ../assets/512 folder is wrong.