Nextjs Folder Routing Inside Pages Sub-Folder - next.js

I am new to Nextjs and Stackoverflow so I will try to describe my issue as best as possible.
I have created the following folder structure in my project:
pages
api folder
index.js
sys-admin folder
createvenue.js
createuser.js
index.js
Inside sys-admin>index.js, I have a button with an onClick handler that uses next/router to push to the createvenue.js route. When I type in the URL http://localhost:3000/sys-admin/createvenue, I can see the createvenue.js page however, when I click the button in the http://localhost:3000/sys-admin page, I am directed to http://localhost:3000/createvenue which gives me a 404. My understanding was that the folder name (in this case sys-admin) would become the root and would be added to the router path to make the URL http://localhost:3000/sys-admin/createvenue.
Here is my sys-admin>index.js code:
import { useRouter } from "next/router";
export default function CreateCustomer() {
const router = useRouter();
const handleSubmit = () => {
router.push("/createvenue");
};
return (
<>
<form onSubmit={handleSubmit}>
<button className="btn btn-filled">Create New Customer</button>
</form>
</>
);
}
Here is my createvenue.js code:
import { useRouter } from "next/router";
export default function CreateVenue() {
const router = useRouter();
const handleSubmit = () => {
router.push("/createusers");
};
return (
<>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Enter venue name" />
<button className="btn btn-filled">Next</button>
</form>
</>
);
}
I've also tried adding /sys-admin to router.push("/sys-admin/createvenue"); but it still doesn't work.
Is there a way to get next/router to add the sys-admin root to the URL?

The default Behaviour of the form is to refresh the Page once it submitted. You have to prevent the form event from refreshing the page.
export default function CreateVenue() {
const router = useRouter();
const handleSubmit = (event) => {
// preventing the form event from refreshing the page
event.preventDefault()
router.push("/createusers");
};
return (
<>
<form onSubmit={(e)=>handleSubmit(e)}>
<input type="text" placeholder="Enter venue name" />
<button className="btn btn-filled">Next</button>
</form>
</>
);
}

Related

Error in Rest Parameter in Fetcher Function SWR

So here I am developing a web app. I use supabase as the database and SWR as the React Hooks. I have followed the step by step on YouTube, but then I encountered the following problem. In the index.tsx file there is an error regarding the rest parameter in the following fetcher function, even though the function is a template function provided by SWR. The error says, "Rest parameter 'args' implicitly has an 'any[]' type." .How should I fix it?
const Home: NextPage = () => {
const [myPosts, setMyPosts] = useState([])
const fetcher = (...args) => fetch(...args).then(res => res.json())
const {data, error} = useSWR('/api/get-posts', fetcher, {refreshInterval: 200})
console.log(data)
useEffect(() => {
if (!data) return
setMyPosts(data.data)
}, [data])
return (
<div className={style.wrapper}>
<Header />
<Banner />
<main className={style.main}>
<div className={style.content}>
<CreatePost />
<Feed posts={myPosts}/>
</div>
<div className={style.infoContainer}>
<About />
</div>
</main>
</div>
)
}
export default Home
I hope that my data in database can be fetched and rendered in my Next.js project.

How to use Next.js <Link> prefetch for a <button>? (And avoiding a double selection while navigating with Tab key)

Accessibility best practices suggest using <button> for button elements.
Prefetching for Next.js can be done via <Link>.
However, when you combine the two and use the Tab key to navigate, it will essentially select that button twice. E.g.
<Link href="#">
<a>
This selects once
</a>
</Link>
<Link href="#">
<a>
<button>
This selects twice
</button>
</a>
</Link>
You could do something like this:
<button
onClick={() => { window.location.href "#" }
>
This only selects once
</button>
But that doesn't prefetch.
You can use router.prefetch to fetch the route before going to the page. Check this for more details
export default function Login() {
const router = useRouter()
const onClick = useCallback((e) => {
router.push('/dashboard')
}, []);
useEffect(() => {
router.prefetch("/dashboard"); // Prefetch the dashboard page
}, [])
return (
<button onClick={onClick}>Login</button>
)
}
this is for nuxt
you don't need to do that way, you can just add props and value into nuxtlink
<NuxtLink
id="home-link"
:to="localePath('/')"
exact
active-class="nav-active"
tag="button"
class="btn btn-primary"
>
Home/Any Name
</NuxtLink>
for next top answer is right
export default function Login() {
const router = useRouter()
const onClick = useCallback((e) => {
router.push('/dashboard')
}, []);
useEffect(() => {
router.prefetch("/dashboard"); // Prefetch the dashboard page
}, [])
return (
<button onClick={onClick}>Login</button>
)
}

Pushing data to object in different component using POST

TL;DR I want to show submitted posts instantly instead of having to refresh my page
Using the Wordpress REST API I am able to create a new post without any issue. The post is being displayed as soon as the page refreshes, so what I want to do is update the posts object in my Hello.vue file as soon as I create that post so I don't need to refresh to show my newest posts.
I'm not really sure where to start - I've removed all of the experiments I've done so far (importing Post in Create, defining props, pushing to an array, reading about object reactivity on the official Vue documentation, nothing helped).
My App.js consists of the <router> object which shows Hello.vue and a component called Create which displays the Create.vue component. This is how my app currently looks like:
My App.vue file:
<template>
<div id="app">
<section class="posts">
<router-view></router-view>
<create></create>
</section>
</div>
</template>
<script>
import Create from '#/components/Create.vue'
export default {
name: 'app',
components: {
Create
}
}
</script>
<style lang="scss">
#import '../src/assets/styles/style.scss'
</style>
My Hello.vue which displays all the posts:
<template>
<div>
<section class="posts__Feed">
<ul class="posts__List">
<post v-for="item in posts" :item="item" :key="item.id"></post>
</ul>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
import Post from '#/components/Post.vue'
export default {
name: 'hello',
props: ['responseData'],
components: {
Post
},
data () {
return {
posts: []
}
},
beforeCreate () {
this.$http.get(postsUrl).then((response) => {
this.posts = response.data
})
}
}
</script>
And finally, the Create.vue file which creates the post:
<template>
<div>
<section class="posts__Create">
<form class="posts__CreateForm" v-on:submit="createPosts">
<div class="posts__CreateFormWrapper" v-bind:class="{ 'is-Loading': loading }">
<p>
<input v-model="formInfo.title" type="text" name="title" id="title" placeholder="Name" :disabled="formSent">
</p>
<p>
<textarea v-model="formInfo.content" name="content" id="content" cols="20" rows="10" maxlength="140" placeholder="Message" :disabled="formSent"></textarea>
</p>
<p>
<button :disabled="formSent">Send</button>
</p>
</div>
</form>
</section>
</div>
</template>
<script>
var postsUrl = '/wp-json/wp/v2/posts/'
export default {
name: 'create',
data () {
return {
formInfo: [],
responseData: [],
loading: false,
formSent: false
}
},
methods: {
createPosts (e) {
e.preventDefault()
var info = this.formInfo
// Check if fields are empty
if (this.formInfo.title && this.formInfo.content) {
this.loading = true
// POST
this.$http.post(postsUrl, info).then((response) => {
this.formSent = true
this.loading = false
// get body data
this.responseData = response.data
})
}
} // EOF createPosts
}
}
</script>
Any help would be much appreciated!
I ended up using an event bus as suggested by wotex. First, I've createad a file called bus.js with the below code:
import Vue from 'vue'
export const EventBus = new Vue()
Next, import bus.js to both .vue layouts using:
import { EventBus } from '#/bus.js'
Now emit the event as soon as a new post is created (this is sitting in my axios POST request inside the Create.vue file):
EventBus.$emit('newPost', this.responseData)
And finally, check if the event has happened on the other end (my Hello.vue file):
EventBus.$on('newPost', function (postData) {
Thanks for pointing me in the right direction!

(login) submit with FormControl in react

iam using the latest version of meteor & react. Yesterday I switched to the newest version of bootstrap. Before that everything worked just fine now I canĀ“t fix my (really noobish) problem.
import React, {Component} from 'react';
import { FormControl, , etc. } from 'react-bootstrap';
export default class Login extends Component {
login(event) {
event.preventDefault();
var username = this.refs.inputName.refs.input.value.trim();
var password = this.refs.inputPw.refs.input.value.trim();
Meteor.loginWithPassword(username, password, function (error) {
if (error) {
...
}
else {
FlowRouter.go('/c/' + Meteor.user().username);
}
});
this.refs.password.refs.input.value = "";
}
render() {
return (
<Row>
<Col xs={3} xsOffset={4}>
<form onSubmit={this.login.bind(this)}>
<FormGroup>
<ControlLabel>Willkommen</ControlLabel>
<FormControl
type="text"
placeholder="Benutzername"
ref="inputName"
name="username"/>
</FormGroup>
<FormGroup>
<FormControl
placeholder="Password"
ref="inputPw"
name="password"
type="password"/>
</FormGroup>
<FormGroup>
<Col smOffset={2} sm={10}>
<Button bsStyle="primary" label="Login" id="loginButton" type="submit" active>Login</Button>
</Col>
</FormGroup>
</form>
</Col>
</Row>
);
}
In my previous solution I used a simple input form. Due to deprecation I switched to this formControl stuff. Now it seems that
<form onSubmit={this.login.bind(this)}>
login never gets called. Console.log(username) returns undefined.
Thanks in advance and many greetings.
//edit 1:
It seems like Iam not the only one with this problem.
React-bootstrap Form getValue not a function
This helped me a lot to find my solution:
import ReactDom from 'react-dom';
var username = ReactDom.findDOMNode(this.refs.inputName).value;
var password = ReactDom.findDOMNode(this.refs.inputPw).value;

Deactivate input in react with a button click

I have this basic component and I want the textfield to be deactivated or activated whenever I click on a button. How can I achieve this?
This is my sample code:
import React from "react";
import Button from 'react-button'
const Typing = (props) => {
var disabled = "disabled";
var enabled = !disabled;
const handleUserInput = (event) => props.onUserInput(event.target.value);
const handleGameClik = (props) => {
disabled = enabled;
}
return(
<div>
<input
className = "typing-container"
value = {props.currentInput}
onChange = {handleUserInput}
placeholder=" ^__^ "
disabled = {disabled}/>
<Button onClick = {handleGameClik}> Start Game </Button>
<Button> Fetch Data </Button>
</div>
);
};
A simplified solution using state could look like this:
class Typing extends React.Component {
constructor(props) {
super(props);
this.state = { disabled: false }
}
handleGameClik() {
this.setState( {disabled: !this.state.disabled} )
}
render() {
return(
<div>
<input
className = "typing-container"
placeholder= " type here "
disabled = {(this.state.disabled)? "disabled" : ""}/>
<button onClick = {this.handleGameClik.bind(this)}> Start Game </button>
<button> Fetch Data </button>
</div>
);
}
};
Working Codepen here.
** 2019 **
Another option is to use, react-hooks' hook useState.
Edit: In a functional component
import React, {useState} from 'react';
function Typing(props) {
const [disabled, setDisabled] = useState(false);
function handleGameClick() {
setDisabled(!disabled);
}
return (
<div>
<input
className='typing-container'
placeholder=' type here '
disabled={disabled}
/>
<button type='submit' onClick={handleGameClick}> Start Game </button>
<button> Fetch Data </button>
</div>
);
}
This might confuse you, but the guys at React.js actually rebuild every form component and made them look almost exactly like the native HTML component. There are some differences however.
In HTML you should disable an input field like this:
<input disabled="disabled" />
But in React.js you'll have to use:
<input disabled={true} />
The accepted example works because anything not 0 is considered true. Therefor "disabled" is also interpreted as true.
const [disabled , setDisabled] = useState(true)
if(condition){
setDisabled(false)
}else{
setDisabled(true)
}
return
<TextField placeholder="Name" disabled={ disabled} />

Resources