How to view PDF in react sent from Node - javascript

I want to view a pdf sent from my backend (nodeJS)
my route
router.route("/getPdf").post(getPdf);
I need to use "POST" req as my pdfs are saved using user id's which I need to find the pdf
my controller
exports.getPdf = async (req, res) => {
const id = req.body.id;
var pdf = fs.readFileSync(
path.join(__dirname, "..", "/submits", id + ".pdf")
);
res.contentType("application/pdf")
res.send(pdf);
};
react component
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
const PDFPreview = () => {
const { id } = useParams();
useEffect(() => {
try {
var res = axios.post("http://localhost:3000/api/pdf/getPdf", { id });
console.log(res)
} catch (error) {
console.log(error);
}
}, []);
return ("Hi");
};
export default PDFPreview;
on Console logging my response

Related

React Native apisauce can't connect to server network

I'm learning react native and therefore I'm using an api package by the name of "apisauce" version ^2.1.2.
when backend be called with postman, I receive an array of data and when it be called with frontend application, I receive "Network_Error"
My question is what I'm doing wrong?
client.js :
import { create } from "apisauce";
const apiClient = create({
baseURL: "http://127.0.0.1:9000/api",
});
export default apiClient;
listings.js:
import client from "./client";
const endpoint = "/listings";
const getListings = () => client.get(endpoint);
export default { getListings };
App.js
import React, { useEffect } from "react";
import listingsApi from "./app/api/listings";
function App() {
const loadData = async () => {
const response = await listingsApi.getListings();
console.log(response);
};
useEffect(() => {
loadData();
}, []);
return (
<Screen>
</Screen>
);
}
export default App;
And here is the error when I do a console.log:
I have found a solution where instead to set the baseURL to backend URL, I had to set the baseURL to the ip-address of my computer.
information had been found at

Is there a way for me to use the router.query in next js in a function?

So I have this Next.js page.
I'm trying to use the request params and use it in a function, but for some reason it's always undefined. I've tried everything I know.
I know that I don't need to put the id in the function.
I tried using the router in useEffect, wouldn't work.
Here's my code :
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
import axios from 'axios';
export default function id () {
const [ response, setResponse ] = useState("");
const router = useRouter();
const id = router.query.id;
const testFunction = (id) => {
console.log(id);
}
useEffect((id) => {
testFunction();
}, [])
return (
<div>
<p>params: {id}</p>
</div>
)
}
try this
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
import axios from 'axios';
export default function id () {
const [ response, setResponse ] = useState("");
const router = useRouter();
const id = router.query.id;
const testFunction = (id) => {
console.log(id);
}
useEffect((id) => {
testFunction();
}, [router])
return (
<div>
<p>params: {id}</p>
</div>
)
}
First thing first, you need to name your file with the name of your parameter, (example: [id].tsx)
Note: If you put it inside a folder (like the image), the path will be http://localhost:3000/folder-name/your-param
And then, try this code:
import React from 'react'
id.getInitialProps = ({ query }:any) => {
const { id } = query
return { id }
}
export default function id({id}:any) {
console.log(id); // You can use the query outside the return by calling `id`
return (
<div>
<p>params: {id}</p>
</div>
)
}

Delay in Authentication using React

I use React for frontend and Node.js in backend and Postgre for database.
I have create my own API for authenticating user and using useState and useContext hook to store the login status of the user.
I also setup a Redirect function after successful login but the useState is taking a while to update the login status of user and because of that the page is not being redirect.
I tried using async and await while fetching the data from the server but still there is delay in authenticating the user.
I also tried to follow some blogs like this
This context state handle the login functionality and update the login status within the component.
import React, { createContext, useContext, useState } from "react";
import { GlobalContext } from "./GlobalState";
export const LoginAuth = createContext();
export const ProvideAuth = ({ children }) => {
const auth = useProvideAuth();
return <LoginAuth.Provider value={auth}>{children}</LoginAuth.Provider>;
};
export const useAuth = () => {
return useContext(LoginAuth);
};
const useProvideAuth = () => {
const [user, setUser] = useState(null);
const { setIsLogin } = useContext(GlobalContext);
const login = async (userDetails) => {
const response = await fetch("http://localhost:4000/api/v1/login/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(userDetails),
}).catch((err) => console.log(err.message));
const data = await response.json();
if (data?.error) {
setUser(false);
} else {
setUser(data);
setIsLogin(true);
}
};
return { user, login };
};
This state used to update the login state throughout the app
import React, { createContext, useState } from "react";
export const GlobalContext = createContext();
export const GlobalProvider = ({ children }) => {
const [isLogin, setIsLogin] = useState(false);
return (
<GlobalContext.Provider value={{ isLogin, setIsLogin }}>
{children}
</GlobalContext.Provider>
);
};
Private Route Code
import React, { useContext } from "react";
import { Redirect, Route } from "react-router";
import { GlobalContext } from "../State/GlobalState";
const PrivateRouteLogin = ({ children, ...rest }) => {
const { isLogin } = useContext(GlobalContext);
return (
<Route
{...rest}
render={({ location }) => {
return isLogin ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location },
}}
></Redirect>
);
}}
/>
);
};
export default PrivateRouteLogin;
You can have an another value for your loginStatus
false = not logged in
true = logged in
pending = for collect all data
in this situation you can have a backdrop(loading) that show over your website till detect loginStatus

Axios mock adapter giving error 'Error: Request failed with status code 404'

I have a component in which I am making an API call on mount
import * as React from 'react';
import axios from 'axios';
import './index.scss';
// import {axiosInstance} from '../../mocks/index';
// axios(client)
// axiosInstance(axios);
const FeatureTable = () => {
React.useEffect(() => {
axios.get("http://localhost:8080/users").then(function (response: any) {
console.log(response.data);
});
}, []);
return (
<div className="container">
</div>
)
}
export default FeatureTable;
And I have setup my mock adapter in a different folder like this
const Axios = require("axios");
const MockAdapter = require("axios-mock-adapter");
import featureTable from './table';
export const axiosInstance = Axios.create();
const mock = new MockAdapter(axiosInstance, { delayResponse: 1000, onNoMatch: "throwException" });
featureTable(mock);
In my table file, I have this code -
const users = [{ id: 1, name: "John Smith" }];
const featureTable = (mock: any) => {
mock.onGet("http://localhost:8080/users").reply(200, users);
}
export default featureTable;
Upon running the code, I get 404 error not found. Please help with the fix.
First of all: you have to use the same axios instance with both places: to setup the mock response and to make the actual call. When I want to mock some API I usually create and export the axios instance in a separate file, and just import it where I need it. like so:
// dataAPI.js
import axios from 'axios';
export const dataAPI = axios.create(); // general settings like baseURL can be set here
// FeatureTable.js
import React, { useEffect } from 'react';
import { dataAPI } from './dataAPI';
export const FeatureTable = () => {
useEffect(() => {
dataAPI.get('http://localhost:8080/users').then(something);
}, []);
return (<div>something</div>);
};
// mock.js
import { dataAPI } from './dataAPI';
import MockAdapter from 'axios-mock-adapter';
import { users } from './mockData.js'
const mock = new MockAdapter(dataAPI);
mock.onGet('http://localhost:8080/users').reply(200, users);
I want to point out axios-response-mock as an alternative to axios-mock-adapter. Disclaimer: I'm the author of that library. I was a bit frustrated by mock-adapter because I didn't find the API intuitive and it has limitations (e.g. can't match URL params in conjunction with POST requests) and that it would not let unmatched requests pass-through by default.
In your table file, you have to pass the relative path, not the absolute one.
const users = [{ id: 1, name: "John Smith" }];
const featureTable = (mock: any) => {
mock.onGet("/users").reply(200, users);
}
export default featureTable;

How can I mock return data from a custom hook in React/Jest?

I have a custom hook called useFetch which simply fetches data and returns it, in my component test I want to just mock this hook to return some fake data, how can I go about doing this?
import React, { useEffect, useState } from 'react';
export const useFetch = (url: string) => {
const [data, setData] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(url);
const json = await res.json();
setData(json);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [url]);
return data;
};
const App = () => {
const config = useFetch(`/api/url`);
return (
<div></div>
);
};
export default App;
Is there anyway I can mock useFetch so that const config is set to some dummy data in my Jest test?
I Will suggest to put your hook in separate file lets say useFetch.js conntains
import { useEffect, useState } from "react";
export const useFetch = (url: string) => {
const [data, setData] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(url);
const json = await res.json();
setData(json);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [url]);
return data;
};
Keeping your app component file like follows
import React from "react";
import { useFetch } from "./useFetch";
const App = () => {
const config = useFetch(`/api/url`);
return (
<div></div>
);
};
export default App;
with above split you can easily mock your hook, example test file as follows
import React from "react";
import { render } from "#testing-library/react";
import App from "./App";
// mock config
const mockConfig = {
data: "mock data"
};
// this will mock complete file, we have provided mock implementation
// for useFetch function
jest.mock("./useFetch", () => ({
useFetch: () => mockConfig
}));
test("should render with mock useFetch", () => {
const { getByText } = render(<App />);
// test logic goes here
});
Assuming all the files are in same directory.
You could try to mock the fetch library.
In the test setup:
global.fetch = jest.fn()
And then in your test:
global.fetch.mockResolvedValue({ json: () => ({ data: "" })})

Categories