What are the differences between Next.js 13 server components and client components? - next.js

I'm trying to understand the differences between Next.js 13 server components and client components, and I have a few questions:
If the server component doesn't have the ability to access hooks, what is the benefit of using it, and how can users interact with it?(state, reactivity)
Are both client components and server components SEO-friendly, or is one better for SEO than the other?
Can we hide API endpoints with client components like we can with server components?
A sample situation:
app/abc/page.tsx
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
Error:
"useState" is not allowed in Server Components.ts(71001)

All Next components have ability to access hooks. But for example useEffect will be executed only in client side.
Server component better for SEO. Because for search engines SSR page looks like static HTML already generated on server.
Hide like SSR - no. Because components rendered in server side and all method required for render called on server. But user requests will be on client side and with SSR and with CSR. But Next offers a built-in proxy function
Yes, with app dir exists some problems.
This approach allows you to make SSR component without getServerSide props and with some others new features. But this is beta and if for you it creates some problem, dont use app dir, use getServerSideProps

Related

Hiding Storyblok API-Key

I'm using Next.js with Storyblok and recently made use of the react-next-boilerplate.
I noticed that they put the preview token in the _app.js, so essentially publish it:
storyblokInit({
accessToken: "your-preview-token",
use: [apiPlugin],
components,
});
If I use an environment variable instead, which isn't available on the client, I get the error
You need to provide an access token to interact with Storyblok API
in the client. That's because (I think) my components use StoryblokComponent, which makes use of the global Storyblok state. So I wonder:
Should I ignore this error, as I don't plan to interact with the Storyblok API other than using it for component rendering (all the data comes from the server, as far as I understand the concept of static site generation), and component rendering seems to be still working?
Should I just publish the preview token?
Should I create two tokens, one for the server and one for the client?
Setting the token to process.env.STORYBLOK_API_KEY || "NULL" (where "NULL" can be anything except the empty string) also works (no more errors) but seems like a weird solution.
I don't really understand why they combine these two things, component rendering and data fetching, in the same function.
I would use a .env.local file and populate it with:
STORYBLOK_API_KEY=your-preview-token
To use the environment variable inside _app.js you have to pass it to next.config.js like this:
module.exports = {
env: {
STORYBLOK_API_KEY: process.env.STORYBLOK_API_KEY,
}
}
Source: https://nextjs.org/docs/basic-features/environment-variables

eHow to transition away from inline editor on actions on google

In a previous Stack Overflow question, I shied away from using an external webhook on Actions on Google
so I needed to go back to the inline editor. I got that worked out, but now I'm feeling brave again.
I've outgrown the inline editor and want the ability to develop my code on my laptop, testing it in Firebase, and publishing to a site for my webhook, presumably where the inline code editor publishes to. In fact, I have already written the require functions and deployed them from Firebase. So the full functionality is ready to go, I just need to hook it up properly to Actions on Google.
What I have now in Actions on Google, inline editor, is more of a stub. I want to merge that stub into my more fullblown logic that I have in Firebase. Here is what is in the inline editor:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
app.handle('intent_a_handler', conv => {
// Implement your code here
conv.add("Here I am in intent A");
});
app.handle('intent_b_handler', conv => {
// Implement your code here
conv.add("Here I am in intent B");
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
When I search on the Internet, I see discussion from the point of view of Dialogflow, but like I say, I'm in "Actions on Google". I want to transition away from the inline editor, taking what I already have, as a basis.Can someone explain how I set that up? I'm happy to do this within the context of the Google ecosystem.
To test your own webhook locally on your own system I would recommend incorporating a web app framework such as express. With express you can host code on your local machine and make it respond to request from Actions on Google. In your case you would replace this will all the code related to the Firebase functions package. Here is an example of what a simple webhook for Actions on Google looks like:
const express = require('express');
const bodyParser = require('body-parser')
const { conversation } = require('#assistant/conversation');
const exprs = express();
exprs.use(bodyParser.json()) // allows Express to work with JSON requests
const app = conversation();
app.handle('example intent', () => {
// Do something
})
// More app.handle() setups
exprs.post('/', app);
exprs.listen(3000);
With this setup you should be able to run your own application locally. The only thing you need to do is install the required dependencies and add your own intent handlers for your action. At this point you have a webhook running on your own machine, but that isn't enough to use it as a webhook in Actions on Google because it runs locally and isn't publicly available via the internet.
For this reason we will be using a tool called ngrok. With ngrok you can create a public https address that runs all messages to your local machine. This way you can use ngrok address as your webhook URL. Now you can just make as many code changes as you want and Actions on Google will automatically use the latest changes when you develop. No need to upload and wait for Firebase to do this.
Just to be clear: Ngrok should only be used for development. When you are done with developing your action you should upload all your code to a cloud service or host it on your own server if you have any. A (free plan) ngrok URL usually expires every 6 hours. So its not a suitable solution for anything other than development.

Is it possible to access a real API in React Storybook

I am using Storybook to test my React UI components.
However, when I get to a point where my Action makes an Axios request, I get a 404 response.
Below is the code used in a react action file:
assume the axios instantiation, thunk implementation and action definitions.
getDelayedThunkRes: () => {
return (dispatch) => {
dispatch(delayedResActions.getInitialRes());
axios.get("/test").then(success => {
console.log(success);
}).then(err => {
console.log(err);
})
}
}
localhost:8080 is my real server that I want to connect to. Obviously it should throw me an error because my storybook is running on 9009. How can I connect the two?
Note, it works for my Create React App. Create React App package gives a provision to proxy all the calls to a server using "proxy" field in package.json
Are there any similar tools in Storybook, or is Storybook supposed to be used solely with static mock data?
Alright, I found an amazing post on how to create a middleware for React storybook for APIs
https://medium.com/#wathmal/adding-a-router-middle-ware-to-react-storybook-4d2585b09fc
Please visit the link. The guy deserves the due credit.
Here is my implementation of it in ES5 (somehow Storybook middleware is unable to transpile):
create this middleware.js inside .storybook directory:
const express = require('express');
const bodyParser = require('body-parser');
const expressMiddleWare = function(router) {
router.use(bodyParser.urlencoded({extended: false}));
router.use(bodyParser.json());
router.get('/test', function(req, res) {
res.send('Hello World!');
res.end();
});
}
module.exports = expressMiddleWare
Caveat: You will have to restart Storybook every time you make a change in the middleware.
With this, I am able to make a call from my react actions.
Next, I will try to implement express HTTP proxy middleware to redirect these storybook middleware calls to my real express server.
Edit 1:
The new technique seems to be using decorators, especially with stroybook-addon-headless.
Storybook add on for setting server urls
https://github.com/ArrayKnight/storybook-addon-headless
I am yet to try

Why component is called twice in Next.js?

This is my pages/index.js of my next.js project
const Index = () => {
console.log('Index Component Called');
return (
<div>Hello</div>
)
}
export default Index;
The console log function is called twice on CLIENT side and one time on next.js node SERVER
I guess because Pages in next.js are server side rendered (or pre-rendered).
So in this case when next.js is rendering your page(server side), the script will console.log("Index Component Called") then on your frontend react it's hydrating so all the code coming from the server should be executed again.
In next.js you can execute Server Side code inside getInitialProps, and in pages only not components.

How to integrate WooComerceAPI into React?

I wanted to receive data to my site on React through the API.I did everything as stated in the documentation, performed the installation of npm install --save woocommerce-api, created the object with parameters as in the documentation http://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#pagination
import React, { Component } from 'react';
import '../App.css';
import WooCommerceAPI from 'woocommerce-api';
class Goods extends Component {
WooCommerce = new WooCommerceAPI({
url: 'http://portland.com/wp/', // Your store URL
consumerKey: '**KEY**', // Your consumer key
consumerSecret: '**KEY**', // Your consumer secret
wpAPI: true, // Enable the WP REST API integration
version: 'wc/v2' // WooCommerce WP REST API version
});
render() {
return(
<div className="GoodsMain">
<div className="Goods">
<img src="/images/photo.png" alt="appletv"/><br/>
<div className="TextAlign">
<span className="NameOfGood">{WooCommerce.get('products/1').name}</span><br/>
<span className="StyleOfGood">black</span><br/>
<span className="PriceOfGood">$49.99</span>
</div>
</div>
</div>
);
}
}
export default Goods;
But I get Line 20: 'WooCommerce' is not defined no-undef
Can u help me integrate correctly API in my site?
I Think you have to use the oauth authentication for getting the data from the woo-commerce rest api because your wordpress is on the server where there is no ssl certificate.
Try this way:
1). Use axios library (https://alligator.io/react/axios-react/) to call the WooCommerce Rest API.
2). To simplify the authentication process, make sure you enable SSL on your Wordpress hosting (I tried authenticate on the non SSL, it appears the process was not that easy, compared the SSL one).
3). Follow the steps from this link to generate the WooCommerce Rest API key
https://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#authentication
4). Once everything setup, test retrieve list of products using Postman (https://www.getpostman.com/).
[GET]
https://{{host}}/{{wordpressFolder}}/wp-json/wc/v2/products/
[HEADER]
// Inside your React code, do this:
const basicToken = btoa(PRODUCTS_CONSUMER_KEY+':'+PRODUCTS_CONSUMER_SECRET)
Authorization: Basic ${basicToken}

Resources