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>
)
Related
I am trying to fetch data from a Supabase table called "profiles" with Next.js 13 and the app directory. I am trying to take advantage of the new next.js fetching methods, my code looks as follows:
export const revalidate = 0;
export default async function getData() {
const { data: profiles } = await supabase
.from("profiles")
.select("*")
.eq("is_host", true);
console.log(profiles);
return { profiles };
if (!profiles) {
return <p>No hosts found</p>
}
The problem is that this code seems to be wrapping the array returned from Supabase in an object.
The data returned looks like this:
{data:
[
{
"id":"feef56d9-cb61-4c4d-88c6-8a8d7c9493d9",
"updated_at":null,
"username":"username",
"full_name":"Full Name",
"avatar_url":"URL",
"website":null,
"is_host":true,
"bio":null,
"languages":6
}
]
}
When I use useState and useEffect instead, the data is returned as expected, and I can map through it.
Does anybody have an idea why, and how I can prevent that?
Thanks in advance.
I worked it out, through a subsequent error, which I as able to solve thanks to the question I asked here and the helpful hints I got from there.
return { profiles };
Returns the array inside an object.
By removing the {} I was able to fetch the array inside of it.
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>```
I have been trying for months to figure out how to display a firestore timestamp in react.
In December 2019, the solution I accepted on this post worked. It no longer works. I'm back to stuck.
I have a firebase.js helper to record dates with:
class Firebase {
constructor() {
app.initializeApp(config)
this.firestore = app.firestore();
this.auth = app.auth();
this.serverTimestamp = app.firestore.FieldValue.serverTimestamp;
}
I use that helper in forms to record the date an entry is created like so:
await Firebase.firestore.collection("blog").doc().set({
title: values.title,
createdAt: Firebase.serverTimestamp()
That correctly saves a date into the firestore document that looks like this:
When I hover over the date, it shows 'timestamp'. I am able to order the data returned from firestore by reference to the createdAt date - so it's curious that the timestamp can be used to sort the documents but cannot be used to print the date on the screen.
When it then comes to outputting the date, I am back to getting all the same errors I reported in the previous post - but the solution that worked in December, no longer works. I have seen a discussion in the firebase slack channel that a recent release of firebase has had some unintended consequences - is there any way to check if broken timestamps is one of them?
When I try:
{currentPost.createdAt.toDate().toISOString()}
TypeError: Cannot read property 'toDate' of undefined
When I try:
{currentPost.createdAt.toDate()}
TypeError: Cannot read property 'toDate' of undefined
When I try:
{new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
TypeError: Cannot read property 'seconds' of undefined
When I try (I know this won't work but just trying to find insights that might help solve this problem):
{currentPost.createdAt}
Error: Objects are not valid as a React child (found: object with keys
{seconds, nanoseconds}). If you meant to render a collection of
children, use an array instead.
I have seen some posts which say the date is undefined because the call on firebase hasn't returned a value yet, but when I console.log the whole currentPost, I get a value for created At, which is:
createdAt: t seconds: 1586495818 nanoseconds: 888000000
The part of this that looks suspicious is the "t". Does it represent something that I'm supposed to do something with in order to access the timestamp? Does anyone know how to investigate what the 't' represents?
I have seen this post and this post, and note that each of the answers to it suggest that the .toDate() extension should help to convert a firestore timestamp to something that can be output. None of those solutions work here.
Has anyone figured out a current solution that allows to both save and output a date from firestore?
Strange - I don't understand why or how this works, but it does.
I changed the useEffect to be async - as follows.
function ReadBlogPost () {
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState({});
let { slug } = useParams();
useEffect(() => {
const fetchData = async() => {
try {
const response = await Firebase.firestore
.collection("blog")
.doc(slug)
.get();
console.log('response', response);
let data = { title: 'not found' };
if (response.exists) {
data = response.data();
}
setCurrentPost(data);
setLoading(false);
} catch(err) {
console.error(err);
}
};
fetchData();
}, []);
Then in the render, I can use:
{!loading && new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
Fingers crossed this works for more than a few months.
I was facing the same problem. The solution is simple for me, You have to first check if the timestamp exists or not.
{data.time === undefined ? (
<div>Time is not defined</div>
) : (
<div> {data.time.toDate().toLocaleTimeString("en-US")}</div>
)}
After that, you can do whatever you want.
(Frist time answering any questions, If i made any mistake, please do tell)
This worked for me:
{data.timestamp.toDate().toLocaleTimeString("en-US")}
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