Passing props via route Sveltekit - url-routing

I am using Svelte+Sveltekit without any routing libraries.
What I would like to do is pass an object to a route, from another page via an <a> tag (or otherwise).
On one page I have a list of objects, for each object I render an item:
// home.svelte
<-- start of page -->
{#each users as user}
<a href="users/{user.username}" sveltekit:prefetch/>
{/each}
<-- end of page -->
The user object above has a few key-value pairs I want to render in the /users/{username} - which is created as a slug route:
// routes/users/[slug].svelte
<script context="module">
export async function load(ctx) {
let data = ctx.page.params;
// I'd like to be able to pass the whole user object from the <a> tag in home.svelte, and access it from ctx.page.params if possible
return { props: { slug: data.slug, user: data.user } }
}
</script>
<script>
export let slug;
export let user;
</script>
<div>
<h1>{slug}</h1>
<h1>{JSON.stringify(user)}</h1>
</div>
Is it possible to do it this way, or do I need a different approach/routing library?

I think it okay to do this. You can get the {user.username} in users/[slug].svelte by export the load function with 'page' parameter. You may try to modify it as below. You may check out the svelteKit online document here
export const load = ({ page }) => {
var username = page.params.slug; //slug refer to [slug].svelte
return {
props: {
user: GetUserByName(username);
}
};
...

You can use the 'query' param
// home.svelte
//use a query string converter library
<a href="users/{user.username}?{objectToQuery(user)}" sveltekit:prefetch/>
then in load function
return {
props: {
slug: page.params.slug,
user: queryToObject(page.params.query)
}
}
but your safest bet is to use a store.
<div>
<h1>{slug}</h1>
<h1>{JSON.stringify($user)}</h1>
</div>
In which case you dont need to pass anything.

Related

Why does dynamic page shows the same data per request in Next.js?

I have a dynamic page named [className].js. In it, I'm trying the fetch the data using getServerSideProps. Currently, I have only two sets of data. When I click a link, that's supposed to take me the dynamic page with the className and show the data within it. But, no matter which link I click, it always shows the data of the first one.
Why is this happening? How can I get the data of the specified className?
export default function classPage({ classDetail }) {
const capitalizedClassTitle =
classDetail.title.charAt(0).toUpperCase() + classDetail.title.slice(1);
const classTitle = capitalizedClassTitle.replace(/-/g, " ");
return (
<div>
<NavBar />
<div>This is the page for {classTitle}</div>
<div className="w-20 h-20">
<Image
src={classDetail.classImageURL}
width={classDetail.imageWidth}
height={classDetail.imageHeight}
/>
</div>
</div>
);
}
export async function getServerSideProps({ query: { className } }) {
const res = await fetch(
`http://localhost:3000/api/admin/classes/${className}`
);
const { data } = await res.json();
return { props: { classDetail: data } };
}
I found the solution. In the api pages of [className], I had this line of code wrong.
const classDetail = await Class.findOne({className});
I changed it to await Class.findOne({title: className}) and now it is working as I wished. title was the keyword for className in my Class schema.

In React How to pass Id to another page class component

I need to pass the Id to another Page using Class components. this.props.match.params.group_Id it returns undefined.Here is my code
#page1
<Link to={"/GroupsDetail.js/?group_Id="+item.group_Id}}>Details</Link>
#page2
submit() {
let Id= this.props.match.params.group_Id;
console.log(Id);
let url = 'http://localhost:0000/api/Group/GroupDetailsDisplay?group_Id='+Id;
}
Need to pass that Id into API.Please share your Idea. Thank you
const url = new URL(window.location.href);
const Id = url.searchParams.get("group_Id");
react-router-dom only handles the path parts of the URL, it doesn't do anything with queryString parameter other than include them in the location object.
Locations represent where the app is now, where you want it to go, or
even where it was. It looks like this:
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere',
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
Access the location prop and pass the search property to a new URLSearchParams to parse the queryString.
submit() {
const { location } = this.props;
const query = new URLSearchParams(location.search);
const Id = query.get('group_Id');;
console.log(Id);
let url = 'http://localhost:0000/api/Group/GroupDetailsDisplay?group_Id='+Id;
}
If you wanted to keep the group id on the route's match params then you'll need to define the route path like path="/GroupsDetail.js/:Id", and link to it as <Link to={`/GroupsDetail.js/${item.group_Id}`}>Details</Link>.

Next.js: How do you pass data to a route created dynamically

I have a component that is receiving data:
const ProductTile = ({ data }) => {
let { productList } = data
var [products] = productList
var { products } = products;
return (
<div>
<div className="p-10 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 gap-5">
{products.reduce((products, product) => products.find(x => x.productId === product.productId) ? products : [...products, product], []).map(({ colorCode, defaultColorCode, now, productId, productCode, productDescription, }, index) => {
return (
<Link key={`${productId}${index}`}
href={{
pathname: '/s7-img-facade/[slug]',
query: { slug: productCode },
}}
passHref>
/* template */
</Link>
)
})}
</div>
</div>
)
}
export default ProductTile
It creates a grid of templates each wrapped in a <Link> component which is rendering a dynamic component;
/s7-img-facade/[product]
What I would like is for the dynamic component to have access to products object which is in the ProductTile .
I know that I can do a getStaticProps in the dynamic component to do another request but that seems redundant and not dry...
Any ideas how the dynamic component get access to the products object?
Thanks in advance!
You've got the right idea - you can pass additional properties in the query field, but you'll need to use getServerSideProps to extract those from the query param and pass it to the page component as props. Something like this:
// pages/product.js
...
<Link key={`${productId}${index}`}
href={{
pathname: '/s7-img-facade/[slug]',
query: {
description: productDescription,
slug: productCode
},
}}
passHref
>
/* template */
</Link>
...
// pages/s7-img-facase/[slug].js
export default function S7ImgFacasePage({ description }) {
return <p>{ description }</p>
}
export const getServerSideProps = ({ params }) => {
const description = { params }
return {
props: {
description
}
}
}
So basically you pass it from the first page in params, read that in getServerSideProps of the second page, and then pass that as a prop to the second page component.
You mentioned getStaticProps - this won't work with static pages because getStaticProps is only run at build time so it won't know anything about the params you send at run time. If you need a fully static site, then you should consider passing it as a url parameter and reading it in useEffect or passing all possible pages through getStaticPaths and getStaticProps to generate all your static pages.

How to call an api containing array of strings through my react code

I need to call an api which consists of an array of string. I need to then publish the response from the api in a dropdown menu. Below is what the API holds that I need to call-
Sample api data - [“Leanne Graham”,”Ervin Howell”,”Patricia”]
Below sample code has the API which holds object information
import React, { Component } from "react";
import "../styles/schema.css";
import Params1 from "../components/Params1";
import axios from 'axios';
import Select from "react-select";
class New extends Component {
constructor(props) {
super(props);
this.handleStoreprocSelection = this.handleStoreprocSelection.bind(this);
this.state = {
selectStoreprocOptions : [],
id: "",
name: '',
itemSelected:false
}
}
async getStoreProcOptions(){
const resSchema = await axios.get('https://jsonplaceholder.typicode.com/users') --backend API call in object format
const data = resSchema.data
const options = data.map(d => ({
"value" : d.id,
"label" : d.name
}))
this.setState({selectStoreprocOptions: options})
}
handleStoreprocSelection(){
// alert('You selected me!!')
this.setState({itemSelected: true});
}
componentDidMount() {
// get all entities - GET
this.getStoreProcOptions()
}
render() {
const itemSelected = this.state.itemSelected;
let param;
if (itemSelected) {
param = <Params1 />;
}
return (
<div>
<div>
<form id ="store-proc">
<label>STORED PROCEDURE</label>
<Select id="store-proc-select" options={this.state.selectStoreprocOptions} onChange={this.handleStoreprocSelection} /> --my dropdown
</form>
</div>
{param}
</div>
);
}
}
export default New;
You need a state, let's say an empty array.
You need to call that API, using some of the methods, for example browser built in fetch or 3rd party library axios.
Then you need to update your state with the response you will get from your API.
Finally use your state inside of your component and display whatever you want.
These are the steps you need to follow, if you needed some logic. Since you didn't provide any code, I assume you didn't know from where to start. If you share some code, will be possible to help more.
are you using any library? because the plain HTML form select would be written in lower case <select/>, not <Select/>. if so, please state it out.
in plain HTML: the solution would be to map the array elements into <option/>. so, selectStoreprocOptions from state, as assigned here: this.setState({selectStoreprocOptions: options}).
inside render:
<select>
{
this.state.selectStoreprocOptions.map(selectStoreprocOption => (<option ..> .. </option>)
}
</select>
Edit: Sorry, I've overseen the use of react-select. never used it, according to the API doc it looks good to me. have you checked that your state really contains an array with the expected objects?
probably ignore my post then, sorry again xD

WP Gutenberg, how to pass variables from backend (the save function) to frontend (a React app rendered in the save function output)?

If I have a Gutenberg block for which I gather a string that the user enters, but I want to use that string within a react app rendered in the frontend, how can I pass that string?
Defining a Gutenberg block
save: ({ attributes }) => {
window.thisVariableWillNotBeSeen = attributes
console.log(window) // here `thisVariableWillNotBeSeen` is seen, in the frontend it is not
return (
<div id="test_react"></div>
)
},
Then, a script enqueued as such (within a plugin)
add_action('wp_enqueue_scripts', 'react_enqueue');
function react_enqueue()
{
$asset_file = include(plugin_dir_path(__FILE__) . 'build/test.asset.php');
wp_enqueue_script(
'myBlock',
plugins_url('build/test.js', __FILE__),
$asset_file['dependencies'],
$asset_file['version'],
true
);
}
And scr/test.js
const { render } = wp.element
import { Test} from './components/test'
render(<Test />, document.getElementById(`test_react`))
Within export const Test, if I see there console.log(window) I cannot see the global variable I have added in the save function of before
How could I do this?
As said here https://stackoverflow.com/a/44663473/826815
it can be done by rendering a script or also a dataset property, and later fetch this data through the window object or through the DOM
save: ({ attributes }) => {
return (
<Fragment>
<div id="test_react"></div>
<div id="test_react_data" data-test={JSON.stringify(attributes)}></div>
<script type="text/javascript">{`var test_react= ${JSON.stringify(attributes)};`}</script>
</Fragment>
)
},

Resources