Passing an image dynamically as props to child component - javascript

In my parent component, I'm receiving an object from an API that I later inject an image into as a key/pair value. I then pass that object off to a child component to be rendered, and I have attempted to follow this post to do so:
Load images based on dynamic path in ReactJs
However, despite copying webpack's necessary image import format, I'm still receiving this error.
Error: Cannot find module '../images/test.jpg'
That path can be used directly in the component just fine... but when imported as such... things break.
Here is the code from the child component:
const WorldInfo = (props) => {
return props.world ? (
<div className={props.className}>
<h1>{props.world.map}</h1>
<img src={require(`${props.world.image}`)}/>
</div>
) :
null
}
Thanks for looking friends!

Instead of passing a full path (relative or absolute), pass only the last name (test.jpg). WebPack will detect a dynamic require and will bundle all the files inside the folder, like so: require('../images/' + props.world.image).

Related

Get asset path in Laravel from within React component?

I'm wondering what the best way is to get the asset path for things like images from inside a React component. I'm using Laravel, and the built-in asset() function that you can use in Blade files is exactly what I need, but I need it on the front-end in JS. Seems like Webpack territory, but I'm not sure what setting I need to modify.
The problem arises when my path is more than just the hostname, for example "localhost:3000/myproject/public" instead of just "localhost:3000".
Doing something like....
import myImage from '../../images/my-image.png'
...
<img src={myImage} />
results in a src path of "/images/my-image.png", which is not found, because the image actually resides at "/myproject/public/images/my-image.png"
In the past I've used the not-so-elegant solution of doing:
// react.blade.php
<body data-root-url={{ asset('') }}>
...
</body>
// helpers.js
export const rootUrl = document.querySelector('body').getAttribute('data-root-url')
While this hasn't gotten me into any trouble yet, I'm trying to find a better way, and I also started using Typescript recently and it (understandably) gets cranky about this because it technically could be null.
I've also tried the following in webpack.mix.js:
mix.webpackConfig({
output: {
publicPath: 'http://localhost:3000/myproject/public/',
},
})
but that doesn't seem to have any effect on image paths. Oddly enough though, this did work when running into a similar issue with code-splitting and looking for the JS chunks.
Any thoughts? Thanks!
I fix it by adding a new controller in the routes/web.php file.
Route::get('assets/{path}', function ($path) {
return response()->file(public_path("assets/$path"));
});
Then I added the images inside the folder public/assets/img/test.jpg and called it in my React component normally.
<Card sectioned>
<EmptyState image="/assets/img/test.jpg">
</EmptyState>
</Card>

Creating custom component with <img> for markdown gatsbyjs

I'm trying to create a custom component for my markdown that accepts an image source. I am unable to display the image via the custom component because the image is not found because it doesn't exist
I also realised the image path is generated by GatsbyJS and I have no idea how to retrieve the path of the image in markdown.
I do have a custom component that holds some text but I couldn't do the same thing for images.
Here is a simple markdown with a title and a few words.
index.md
---
title: ToDoApp
---
Hi this is my todoapp app. Below is a bunch of screens
<imageholder src='./screen1.png'></imageholder>
![Image from Gyazo](./screen1.png) <!-- it displays... -->
I've created a custom component named imageholder where it holds some logic (in a near future...) in displaying the image
ImageHolder.js
import React from "react"
export default class ImageHolder extends React.Component {
render() {
return (
<img src={this.props.src} alt="Logo"/>
)
}
}
project-post.js
const renderAst = new rehypeReact({
createElement: React.createElement,
components: {
"imageholder": ImageHolder
},
}).Compiler
And I received this...
This is really tricky since (AFAIK) you can't pass props from page component to custom component with rehype-react. I think you'd need to do something similar to gatsby-remark-images, which locates the images' paths and set them.
I wrote this plugin that mimics gatsby-remark-images, but for custom components like in your case.
Here's the default setting, you can override the component name and pass in additional image transformation options.
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-custom-image-component`,
options: {
// plugin options
componentName: 'image-wrapper',
imagePropName: 'src',
sharpMethod: 'fluid',
// fluid's arguments, see gatsby-plugin-sharp docs
quality: 50,
maxWidth: 800,
}
},
],
},
},
Then use it in your markdown:
<image-wrapper src='./hero.jpg'></image-wrapper>
And get the image props in your custom component.
//src/components/ImageWrapper.js
import React from 'react'
// the result of sharp's image transformation will be passed directly to this component.
// so if you use `fluid` as `sharpMethod`, you'll get
// src, srcSet, base64, aspectRatio, srcSetType, sizes, density, originalImage.
// Please refer to `gatsby-plugin-sharp` docs.
const ImageWrapper = ({ src, srcSet }) => <img src={src} srcSet={srcSet} />
export { ImageWrapper }
The issue is that props are passed as strings to rehype - the component doesn't receive the asset hashed value when the markdown is processed and built by Gatsby. So, the prop isn't the same as the image tag's src once you build the site, and it's not finding the asset hashed file.
This plugin, Gatsby Remark Copy Linked Files, moves your referenced asset files to a public folder, and passes the correctly hashed asset path, but by default only for img, a, audio, and video tags (not for custom components).
To solve for this, move the plugin from node_modules into a /plugin folder in the project root, and add the desired custom components and props at this line. In your case, it looks like it would be:
// Handle a tags.
extractUrlAttributeAndElement($(`a[href]`), `href`).forEach(processUrl)
// Manually added custom tags
extractUrlAttributeAndElement($(`imageholder[src]`), `src`).forEach(processUrl)
Obviously this would be better served as an option for the plugin in a configuration block in gatsby-config, but this worked for me in a pinch.

React Native: How to make modular components using local image and data assets?

create-react-native-app v1.0.0
react-native-cli 2.0.1
react-native 0.52.0
Android API 25
I have several JSON files in ./src/data (aliased as data) and images in ./src/assets/images (aliased as images).
I am making a list of images that are filterable and sortable based on the corresponding data. Additionally, I have different types of images the user can toggle between for compact and expanded view.
From my searching it looks like my plan to reference the image path dynamically from a data object property is not possible and I need to do something like:
import image1 from 'images/'image1.png';
import image2 from 'images/'image2.png';
<Image source={some_expression ? image1 : image2} />
or
<Image source={some_expression ?
require('images/image1.png') : require('images/image2.png')} />
That works for the toggle, but I still have the original problem where I can't actually assign image1 and image2 from my data objects such as:
var image1 = "images/" + data.image1.img
where data.image1.img is the filename.
Is there a way around this where I can dynamically reference the local images for the corresponding data in a reusable component?
Short of hardcoding individual components with the images for each data object, I'm at a loss.
I'm new to React and mobile in general so I may have overlooked something in the documentation or online searching.
You can import your local images in parent of your component and use it as a prop.
<Image source={this.props.localImage} />
Where 'localImage' is imported in parent, like in code below and passed as a prop to child (your component).
import localImage from 'images/some-image.png';
This will maintain reusability and works perfectly.
For anyone with the same issue, here is what I did in order to use a string from my JSON data to reference the corresponding image to change what is shown dynamically.
In Images.js import all static images:
const images = {
img1: require('images/img1.png'),
imgNth: require('images/imgNth.png')
}
export default images;
or alternatively
import _img1 from 'images/img1.png';
import _imgNth from 'images/imgNth.png';
const images = {
img1: _img1,
imgNth: _imgNth
}
export default images;
Then where you want to use them i.e. App.js:
import images from 'images/Images';
import data from 'data/Data';
<Image source = {images[data[index].imgName]} />
Where imgName is a property that contains the exact same string value as one of the properties in the imported images i.e. img1 or imgNth in this example.
Regardless of how many images you have, I would suggest writing a simple script to run through your image folder and auto-generate an Images.js type file. It isn't hard to do and will save you a lot of work, especially if you add or remove images regularly during development so you don't have to manually update it each time.

Accessing $route.params in VueJS

Looking through this documentation:
https://router.vuejs.org/en/essentials/navigation.html
It looks like you can bind the <router-link :to="variableName">Link Text</routerlink> Which is pretty nifty; however, I've had some trouble trying to access route parameters inside of a component I'm trying to build.
So I use this:
<router-link :to="permalink">Title of thing</router-link>
To then direct the router view to pull the forum thread. Using this in the router:
import ForumThread from './views/groupTitle/forumThreadSingle';
// Other routes...
let routes = [
{
path: '/groupTitle/th/:id',
component: ForumThread,
}
];
I can see in the forumthread component that $route.params.id is being passed too it; however, when I try to access it like this:
console.log('The id is: ' + $route.params.id);
It's unable to find the params portion of the object.
VueJS is pretty new to me as well as JavaScript itself. All the examples I've seen show the templates being inline with the router file which is something I am trying to prevent to help keep my code readable and clean.
What adjustments can I make so that I can pass properties to the template file?
Thanks!
If you're using the Vue Loader setup (which has <template></template> tags in the files), you need to use this to reference the $router, if you're doing so within the <script></script> part of the file.
console.log('The id is: ' + this.$route.params.id);
For and one wanting to get params in vue 3 with composition API for vue-router 4.x, it can be achieved using useRoute.
import {useRoute} from "vue-router";
setup(){
const route = useRoute();
const id = route.params.id;
}

Import image using this.props.src in React

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.

Categories

Resources