First up, I'm new to Next and I'm using Next 13.1 with the app directory.
I need a select input in my application that is used to switch between the different years of data I'm looking at.
The data of the entire application (content, side navigation bar, top navigation bar) depends on the selected year, because I need to fetch data from different paths depending on which year is selected.
Currently I am fetching all the data server side, and I am setting a searchParam when the select input value changes. Because the search params can only be accessed in Page components on the server side, I'm converting the search param to a request header using middleware, so every server-side component can access it. This leads to a complete reload of the page every time a link is clicked.
My question is: How do I implement the functionality described above? I am obviously doing something wrong, but I'm new to client / server components and therefore don't know the best design practices.
// The select input:
<StyledTextField select defaultValue={currentYear ?? years.find(year => year.is_active)?.id}>
{years.map(year=> (
<MenuItem value={year.id} key={year.id} className={"yearSelectItem"}>
<Link href={{pathname: pathname, query: {year: year.id}}}>
{year.name} {year.is_active && "(aktiv)"}
</Link>
</MenuItem>
))}
</StyledTextField>
// The middleware:
const requestHeaders = new Headers(request.headers);
requestHeaders.set("x-year", request.nextUrl.searchParams.get("year") ?? "")
const response = NextResponse.next({
request: {
headers: requestHeaders
}
})
return response;
// This is how I access the header in server-side components:
headers().get("x-year")
Related
I'm just new to reactjs-spfx controls. I have a pnpjs control that lists all the pages and it's contents. I should be able to add edit and delete pages using that web part. I want to include in that component the functionality to add a new Web part to the page content when I'm editing it. How do you call that functionality from SharePoint to add new webpart? Please see below picture. Thanks.
I would recommend using pnpjs library for this, it wraps most basic tasks with a nice api. I am adding my own webpart to a page something like this, just to give you an idea:
See https://pnp.github.io/pnpjs/sp/clientside-pages/
const sp = SPFI(...)
// or get the existing page
const page = await sp.web.addClientsidePage(fileName, title);
const section = page.addSection();
const partDefs = await sp.web.getClientsideWebParts();
// find the web part we want to add by guid
const myPartDef = partDefs.find(c => areGuidsEqual(c.Id, MY_GUID));
const part = ClientsideWebpart.fromComponentDef(myPartDef);
part.setProperties({
someProp: someValue
});
section.addControl(part);
await page.save();
I have an assignment and I need to do it. I'm new to react. There are a lot of resources about uploading pictures on the internet, but they all do it in a different way and it's not what I want. I have a component named product upload in functional component format, and when uploading a product, I want the user to select an image from their computer and upload an image to the product, but this will be in base64 format. At the same time, I need to read the pictures of the products from the database, since I will bring this picture while fetch the products. and the user can cancel the image he selected while uploading the product. Can you make a sample react code with these items? really important. I'm new to React and I don't know much about it.I need to do this.
To summarize briefly, I am writing below in bullet points.
1. the user will select an image from his computer and when he
selects this image, it will appear on the screen in a certain size.
2. if the user clicks the upload button, this image will be
uploaded to the database in base 64 format.
3. if the user presses the cancel button, for example, it may be next
to the picture. The picture selected by the user will be
cancelled.
4. Lastly How can I read the picture information in this database and bring the picture back
to the screen.
I will try to briefly summarize what you need to do and provide a minimal working example.
You need to understand before continuing:
What are Client and Server
HTTP Request Get/Post etc
SQL Database
You need a server. The server will receive the base64 image and store it in the db. It also needs to provide a way to request sending the image back.
For your basic example you can use the python webserver. We use sqlite in python to manage the database.
from http.server import BaseHTTPRequestHandler, HTTPServer
from sqlite3 import connect
if __name__ == "__main__":
db = connect('database.db')
cursor = db.cursor()
cursor.execute(
'CREATE TABLE IF NOT EXISTS images (id INTEGER PRIMARY KEY, base64 TEXT)')
class ServerHandler(BaseHTTPRequestHandler):
def do_GET(self):
cursor.execute("SELECT base64 FROM images LIMIT 1")
image = cursor.fetchnone()
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.send_header('Content-Length', len(image))
self.end_headers()
self.wfile.write(image)
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_body = self.rfile.read(content_length)
cursor.execute(
"INSERT INTO images (base64) VALUES (?)", (post_body,))
db.commit()
self.send_response(200)
self.end_headers()
webServer = HTTPServer(("localhost", 8080), ServerHandler)
print("Server started")
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
db.close()
print("Server stopped.")
For the client side aka your react script take a look at the following component. It has an HTML input element that accepts images.
on upload, the image is converted to base64. We then use fetch to send the data to the post method of our python server.
import React from "react";
export default function ImageUpload() {
function convertBase64(file) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
}
async function uploadImage(event) {
const file = event.target.files[0];
const base64 = await convertBase64(file);
fetch("http://localhost:8080/", {
method: "POST",
headers: { "Content-Type": "text/plain" },
body: base64,
});
}
return (
<input
type="file"
id="img"
name="img"
accept="image/*"
onChange={uploadImage}
/>
);
}
Now you got the basic idea but there's a lot of work todo.
Make the python server better by sending correct responses, validating that the input is base64 encoded, etc. Come up with a good SQL table to store your images. Make sure the image you want is returned. For the frontend make the component pretty. Write another component that displays the image from the db. catch errors and lots more...
So i'm trying to paginate some data coming in as a POST request. (Using POST because the data is large and exceeds GET limits). What im thinking I need to do is get the page number were on currently so whenever a user wants to view a particular page, so we can know which page to present. What I don't understand is how to set up the URL to have parameters within the URL. What i'm hoping to achieve is to have a URL like this https://stackabuse.com/sessions/?page=2&limit=3 but what i currently have is https://stackabuse.com/sessions/
app.post('/newdatasessions', checkAuth, cacheMiddleware(15*60), (req, res) => {
if(req.query.limit == 2 && req.query.page == 1 && req.query.order == 'session_uuid DESC'){
res.send(values.slice(0,2));
}
else{
res.send([values[values.length-1]]);
}
})
I don't know how to manage query string to react.
I made component class and it is composed of 3 other components.
It is not show data first time. Users have to select or click but
ton.
It is work well.
But I received a new feature. ;(
When users connect my site who copied url, the page has to show data immediately.
So I added query string. But I don't know when I call function.
I installed query-string.
I tried to use 'shouldComponentUpdate' function, but it was not work.
shouldComponentUpdate(nextProps, nextState) {
if (this.props.location.search.ids !== nextProps.location.search.ids) {
// call some function....
}
return true;
}
for example,
Users connect localhost:3000/my/home
It's ok.
But users connect localhost:3000/my/home?ids=1
It's not ok.
Summary.
I want to show data immediately when user connect to the site by query-string.
to fetch data, the most common way to call api is calling in componentDidMount.
https://reactjs.org/docs/faq-ajax.html
if you are using react-router for your app, you can easily get query string with following feature of react-router .
https://reacttraining.com/react-router/web/example/query-parameters
and then pass query string to your api.
I added componentDidMount and call myfunction.
componentDidMount(){
const query = queryString.parse(this.props.location.search);
if(query.ids !== 'undefined'){
let slice_ids = [];
slice_ids = query.ids.split(',');
if(slice_ids.length > 0){
this.myfunction(1);
}
}
}
Users can access the url.
Thanks #gnujoow
all I would try to make some optional layout in NextJS. My problem is that I have found some method to check the browser URL then serve content according to these URL. But by this way the server content an browser content are no longer identical, hence the schema breaks.
Here an snippet of my trial:
export default ({children, title = 'title' }) => {
var
contact = false;
if (exenv.canUseDOM ){ if (window.location.href==="http://localhost:4000/contact" ) { contact= true}; }
else {const contact = false};
if (contact){ return( <div>Hey it is contact ! </div> ) }
else { // return normal layout
My console returns me predictably:
Warning: Text content did not match. Server:
So... I'm wondering if I have to make some custom settings on a custom NextJS server to grant the backend/frontend behaviors?
Or maybe there is a less expensive solution in the area?
Any hint would be great,
thanks
You can't remove that warning, it is appear because you just render that layout from client side, so there is a different between layout rendered by server and layout rendered by client.
I don't know what variable exenv.canUseDOM is, but you can use process.browser to detect if the current process is server side rendering or not.