I can't show the images from Strapi to my ReactJS (frontend).
This is my Homepage code:
import React from "react";
import useFetch from "../hooks/useFetch";
import { Link } from "react-router-dom";
export default function Homepage() {
const { loading, error, data } = useFetch(
"http://localhost:1337/api/reviews"
);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
console.log(data);
return (
<div>
{data.data.map((review) => (
<div key={review.id} className="review-card">
<h1>{review.attributes.title}</h1>
<img src={'http://localhost:1337/api/reviews?populate=reviewImage'} alt={"Not Working!"}/>
</div>
))}
</div>
);
}
This is the output:
This is the data I'm getting in postman:
So as it is not stated in your initial question, I guess you are using Strapi v4...
With Strapi v4 you have to keep one big change in mind. Strapi V4 doesn’t return media files or relation data by default. Thus, you will need to adapt your request as it is outlined in the docs.
Move to this question to see further details:
https://stackoverflow.com/a/71706954/3406465
To solve your first problem I would suggest to adapt your fetch call. So simply include the populte field (like you already do # img src) and you will get the image data. You can test this with Postman and compare the results.
Then your second problem is that the img src wants to have an url. In your example you would more or less assign the full json response. But as soon as you try to solve your first problem you will see what I mean. Then you can use it similar to this:
<img src={`${REPLACEWITHYOURBASEURL}${review.attributes.reviewImage.data.attributes.url}`}></img>
I'm not sure if I'm missing something, but I don't see any attribute that relates to an image URL.
you fetch the data from http://localhost:1337/api/reviews
you iterate over the data within the return statement
from glancing over your iteration, you point the src to
http://localhost:1337/api/reviews?populate=reviewImage although,
http://localhost:1337/api/reviews doesn't seem to have any attribute that contains an image.
furthermore, unless that API endpoint returns the image itself, that source is incorrect.
My Suggestion:
if it's possible to modify whatever API you're using, i'd do something along this route:
append the direct image URL link to the response you get from
http://localhost:1337/api/reviews
once you've done so, you'd be able to target it just like you did with the title and do something like that:
{data.data.map((review) => (
<div key={review.id} className="review-card">
<h1>{review.attributes.title}</h1>
<img src={review.attributes.image} alt={...}/>
</div>
))}
</div>```
Related
so im currently creating my first Website with Next.js.
Im using Amplify as a host for my website and my database.
However im having trouble to display the response im getting from my database.. I managed to log the response in my console which looks like this:
[
Profile {
name: 'firstActualUser',
position: 'VIP',
createdAt: '2022-02-08T15:39:01.527Z',
updatedAt: '2022-02-08T15:39:07.527Z',
_version: 1,
_lastChangedAt: 6781253702551,
_deleted: null
}
]
My question is how do I render this response into my actual page? Currenty I log my response like this:
const externUsers = DataStore.query(Profile).then(users => console.log(users));
I thought I can simply access this response by just accessing the array like the following:
return (
<div className={styles.container}>
<h1 className={styles.title}>Home</h1>
<p>{externUsers[0].name}</p>
<p>{externUsers[0].position}</p>
</div>
)
However that doesnt work and wouldnt be a nice solution anyways, especially if my response doesnt just contain 1 Profile.
Any Help is appreciated, watched countless tutorials but I just get more and more confused..
Thanks!
I think you are close. You just have to cover the situation where externUsers has not been loaded. (Keep in mind that everything is asynchronous in react.)
Assuming you calling the DB in a useEffect hook
const [externUsers , setExternUsers]= useState();
useEffect(()=>{
DataStore.query(Profile).then(users => setExternUsers(users));
},[]);
then do some handling before returning Jsx:
if(!externUsers) return null;
Else if(externUsers.length===0) return (<>no user</>);
Else
return (
<div className={styles.container}>
<h1 className={styles.title}>Home</h1>
<p>{externUsers[0].name}</p>
<p>{externUsers[0].position}</p>
</div>
)
I'm serving my website from example.org, built with reactjs 16.13.1 and typescript.
I have a component that displays an image like this:
<img alt={""} className={"person-image"} src={person.imageUrl}/>
The person JSON object comes from the backend. ImageUrl is an url that looks like this: https://example.org/api/data/24361/img.jpg. The image is served via a Spring Boot controller.
The image fails to load because for some reason it is rewritten to: https://example.org/example.org/api/data/24361/img.jpg
Why is example.org being repeated?
I inspected the JSON returned from the server and the url is correct: https://example.org/api/data/24361/img.jpg
If I copy paste the url on a browser, it loads correctly, so it's not a reverse proxy problem, or it doesn't seem to be.
If I log the url on the console before it's being passed to <img>, it is correct.
I have some other images being loaded from external domains and they load without any issue.
Is the <img> tag operating some kind of rewriting of the url if the image comes from the same domain and an absolute url is being used? Is there something I'm overseeing?
EDIT: the component code
interface PersonProps {
person: PersonData
clickable?: boolean
}
export function Person({person}: PersonProps) {
const actions = [
new Action(
<><FullscreenOutlined/> Full</>,
() => {
// opens wrong url https://example.org/example.org/api/data/24361/img.jpg
const win = window.open(person.imageUrl, '_blank');
win?.focus();
}
)
]
// prints https://example.org/api/data/24361/img.jpg
console.log(person.imageUrl)
return <Wrapper
actions={actions}>
{/* loads wrong url https://example.org/example.org/api/data/24361/img.jpg */}
<img alt={""} className={"person-image"} src={person.imageUrl}/>
<div className={"person-body"}>
{person.name}
</div>
</Wrapper>
}
I am quite new and having some difficulties getting an output when running a GraphQL query on a shopify scriptTag.
My current code looks like:
const test4 = gql`
query {
scriptTags(first: 4) {
edges {
node {
id
src
}
}
}
}
`;
const GiveData = () => (
<Query query={test4}>
{({ loading, error, data }) => {
if (loading) return "Loading...";
if (error) return `Error! ${error.message}`;
return (
<div>
<p> hi1 </p>
{data.scriptTags.edges.map(({ node }) => (
<div key={node.src}>
<p>
hi2 {node.src}
</p>
</div>
))}
</div>
);
}}
</Query>
);
My page is rendering the "hi1" text paragraph, but the "hi2" and actual data never loads. My console is also not outputting any error.
The query code itself works perfectly if I run it through the Shopify GraphiQL App, so I assume it isn't that. I believe I am doing something wrong within the GiveData constant, but not sure what.
Thanks in advance for any help or hints.
More context:
I have a basic shopify app setup, using react + node.js setup (based on shopify's templates & tutorial).
My server.js file has the script tag scopes included:
...
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products', 'write_products', 'read_script_tags', 'write_script_tags'],
...
I have been able to write a script tag, as it shows up in the
Shopify GraphiQL App. Screenshot of output
.
I am also able to get an output from a different GraphQL query. For example this
const test3 = gql`
query {
shop {
id
}
}
`;
with the same basic GiveData constant above, will output a result if I have ...{data.shop.id}... in my return field.
I am primarily wanting to query the script tags I've been able to write myself (not anything outside my app).
It would help to know the context of your call. In Shopify GraphiQL, clearly you are authenticated, the end point is set, all is well. Move away from that and your responsibilities mount. You can query using a private App API password, or a regular App with an oAuth token that has scoped access to script tags. Which are you?
Without knowing more about what you are doing, it is hard to help you along. Also, the liklihood that Shopify will show you any script tags that do not belong to the API key that created them ie) yours, is minimal.
I have been trying for a while to learn how to build mobile apps with Javascript, and honestly I have no idea how anyone is able to do anything. Everything is broken. Every tutorial I've tried has failed to work for some bizarre reason. I am at my wits end.
I've finally decided to try and be even simpler, and just do the most basic tutorial I can find. What could go wrong. Well, it only took 3 pages of almost no code to completely stop working. I've done this, and I cannot insert anything to my db. My app fetches no data. When trying to add a new task, it gets added then disappears almost immediately, with a message stating insert failed: Method '/tasks/insert' not found (not even an error with some traceback).
The code really couldn't be simpler:
// imports/api/tasks.js
import { Mongo } from 'meteor/mongo';
export const Tasks = new Mongo.Collection('tasks');
// imports/ui/App.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { withTracker } from 'meteor/react-meteor-data'
import { Tasks } from '../api/tasks.js';
import Task from './Task.js';
// App component - represents the whole app
class App extends Component {
handleSubmit(event) {
event.preventDefault();
// find the text field via the react ref
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Tasks.insert({ text, createdAt: new Date() });
// Clear form
ReactDOM.findDOMNode(this.refs.textInput).value = '';
}
renderTasks() {
return this.props.tasks.map((task) => (
<Task key={task._id} task={task} />
));
}
render() {
return (
<div className="container">
<header>
<h1>Todo List</h1>
<form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
<input
type="text"
ref="textInput"
placeholder="Type to add new tasks"
/>
</form>
</header>
<ul>
{this.renderTasks()}
</ul>
</div>
);
}
};
export default withTracker(() => {
return {
tasks: Tasks.find({}).fetch(),
};
})(App);
What is wrong? What am I missing?
The tutorial is indeed out of date and should be updated.
Background
In June 2017 there was a big security issue with allow/deny identified and the feature has been blocked since then.
Meteor allowed you to define client collection, that automatically synced with the server when the methods insert, update, remove were called on the client.
In order to control the access permissions, the allow/deny feature was implemented.
Now without allow/deny you will get the insert failed: Method '/tasks/insert' not found when classing SomeCollectionOnClient.insert but since this feature is obsolete (you will even get a big warning when setting it up), you need to create a server side method and call it from the client in order resolve this issue:
On the server create this method and ensure it is in the import chain from server/main.js:
new ValidatedMethod({
name: 'tasks.insert',
validate(args) {
// better use simpl-schema here
if (!args.text || !args.createdAt) {
throw new Meteor.Error('incompleteArgs', 'args are incomplete')
}
},
run (args) {
// check user permissions...
return Tasks.insert({ text, createdAt })
}
})
In your client component you can then call it via:
// find the text field via the react ref
const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();
Meteor.call('tasks.insert', {text, createdAt: new Date()}, (err, res) => {
// do something on err / on res
})
Note that this couples your component to the server side method and you may rather try to implement some containers for your pages that handle all the connection / pub-sub / method calling activity wile your components solely render content.
More to read / used in this answer:
https://guide.meteor.com/react.html
https://guide.meteor.com/security.html
https://docs.meteor.com/api/methods.html#Meteor-call
https://guide.meteor.com/methods.html#validated-method
I'm working on a google maps project with React. I assign an onClick handler the following method:
getStreetView(lat,lng){
let url = `https://maps.googleapis.com/maps/api/streetview?size=600x300&location=${lat},${lng}&heading=151.78&pitch=-0.76&key=MYAPIKEY`
axios.get(url).then(response=>this.setState({image:response.config.url}));
}
the state = { image: null } is then beeing assigned the url which I later pass on to an image tag to a child component such as <img src={props.image} alt='street view'/>. Everything works like a charm, however I have come across various other solutions such:
function getBase64(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => Buffer.from(response.data, 'binary').toString('base64'))
}
from b4dnewz from the axios documentation. However I can't find a reasonable approach how to display the image in child component with that response type. My question is, is my approach valid? Is there any reasons why I shouldn't be using it like that?
If you are getting the image url from api, then your first method is the right approach, but the
Buffer.from(response.data, 'binary').toString('base64'))
method is used when the image itself is received from server as a binary which is converted to base 64 and given to <img>