Importing static local json file to Vue store (exclude from build) - json

I'm trying to have my add data from a local static JSON file to the Vue vuex store.
I want my JSON file separated from the bundle process, so that i can change the content anytime in future, without rebuilding the whole site.
I have my json file [test.json] in the public folder
And with the following code, i managed to import the data, but its still being bundled on build of the site.
import data from '../public/test';
export const state = () => ({
allData: {}
})
export const mutations = {
SET_ALL_DATA(state, data) {
state.allData = data
}
}
export const actions = {
nuxtServerInit({ commit }) {
commit('SET_ALL_DATA', data)
}
}
I have also tried hosting the JSON file on a web server and doing an axios call to it on nuxtServerInit like so. but the called upon json file still gets bundled, as changing the hosted json file does nothing to update the content.
export const actions = {
async nuxtServerInit ({ commit }, { $axios }) {
const res = await $axios.$get('https://www.amq.fariskassim.com/testjson/test.json')
commit('SET_ALL_DATA', res)
}
}
I'm all out of solutions so if anyone can point me in the right direction, i would be totally grateful

Related

issue in json data fetching and rendering in nextjs

I am trying out a small sample in nextjs. All that the proj does is to fetch json data from a file and try displaying it in list of a component. But the behavior is weird. Its getting into infinite loop and I have no clue what's wrong. Could some one take a look at https://github.com/SamplesForMurthy/sampleCode and help me figure out what the issue is? Not able to fetch the data nor I am able to display.
I cloned and fixed. You don't need to use fs.readFileSync here, or fs at all for that matter. You can simply import the .json file as an arbitrarily named variable then map it out.
Here is how I got the data rendering:
import React from 'react';
import testData from '../TestData/SampleData.json';
import SampleParentComponent from '../components/SampleParentComponent';
function TestPage({ filecontent }) {
console.log(`filecontent: ${filecontent}`);
return (
<div>
<SampleParentComponent data={filecontent}></SampleParentComponent>
</div>
);
}
export const getStaticProps = async ctx => {
console.log(ctx.query);
const filecontent = await testData;
return {
props: { filecontent }
};
};
export default TestPage;
/**
* (property) filecontent: {
data: {
seqNo: number;
contactName: string;
}[];
}
*/

How to save imported JSON file with Expo Filesystem

I have been working on a React Native project with Expo that uses a json file to store local data. I am importing the data like so
import data from '../database.json'
I am making changes (adding and removing) to the imported JSON by using data.push(new_data). These changes are not persistent when I close the app because I cannot figure out how to save them. I have looked at using the expo-file-system library as so:
import * as FileSystem from 'expo-file-system';
...
FileSystem.writeAsStringAsync(FileSystem.documentDirectory + 'database.json', data);
This is from looking at examples in the API documentations. This however always throws promise rejections and doesn't end up writing the file. Can you point me in the right direction?
Also, should I import the database.json in a different way so I will already have the uri to save it to?
The documentation doesn't give an example of it's returned props in promises, so I was overlooking it for longer than I care to admit 😅. I was really dedicated to figuring this out so I could use the Expo solution, and totally missed the return Promise for createFileAsync, so hopefully this saves someone a significant amount of time in the future.
import * as FileSystem from 'expo-file-system';
const { StorageAccessFramework } = FileSystem;
const saveFile = async () => {
const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
// Check if permission granted
if (permissions.granted) {
// Get the directory uri that was approved
let directoryUri = permissions.directoryUri;
let data = "Hello World";
// Create file and pass it's SAF URI
await StorageAccessFramework.createFileAsync(directoryUri, "filename", "application/json").then(async(fileUri) => {
// Save data to newly created file
await FileSystem.writeAsStringAsync(fileUri, data, { encoding: FileSystem.EncodingType.UTF8 });
})
.catch((e) => {
console.log(e);
});
} else {
alert("You must allow permission to save.")
}
}
Use AsyncStorage instead. The react native package is deprecated but working, or use #react-native-community/async-storage and convert json to string (AsyncStorage can only store strings)
Set item
import AsyncStorage from '#react-native-community/async-storage';
...
await AsyncStorage.setItem('myData', JSON.stringify(data))
Get item
const data = await AsyncStorage.getItem('myData')
I found #JayMax answer very helpful however it's only for Android.
On iOS all you need to do is use Sharing.shareAsync and then you can save data to the file. Check this example:
const fileUri = FileSystem.documentDirectory + 'data.txt';
FileSystem.writeAsStringAsync(fileUri, 'here goes your data from JSON. You can stringify it :)', {
encoding: FileSystem.EncodingType.UTF8,
});
const UTI = 'public.text';
Sharing.shareAsync(fileUri, {UTI}).catch((error) => {
console.log(error);
});
If you using AsyncStorage, it only store for small data. Maybe 6mb or 10 mb.
You can use expo fileSystem
import * as FileSystem from 'expo-file-system';
...
FileSystem.writeAsStringAsync(FileSystem.documentDirectory + 'database.json', data);
Convert your data (Type json to string) Such as this:
writeData = async () => {
var persons = ''
await axios.get(`http://192.168.0.48:4000/api/sql/student`)
.then(res => {
persons = res.data
})
await FileSystem.writeAsStringAsync(FileSystem.documentDirectory + `offline_queue_stored.json`, JSON.stringify(persons));
}
#1.If the JSON File is in your Project Folder (PC/Laptop)
import data from './database.json';
#2. If the JSON File is in your Phone
import * as FileSystem from 'expo-file-system';
import * as DocumentPicker from 'expo-document-picker';
this.state = {
fileURI: null,
};
componentDidMount = () =>{
this._pickDocument();
}
_pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({});
this.setState({
fileURI: result.uri
})
let fileData = await FileSystem.readAsStringAsync(this.state.fileURI)
console.log(fileData)
};

Batching with useQuery react hooks getting back undefined

I am currently working on a project which requires me to make multiple queries/mutations. I tried setting up my apollo client with BatchHttpLink and I can see the data I am requesting in the network tab in the browser. It is coming back at an array of objects instead of JSON.
But the issue is when I try to grab the data in my component data is undefined. I tried using HttpLink instead of BatchHttpLink and I can get the data back from the hook.
My suspicion is the shape of the object that comes back from the response is different, I tried looking into documentation but I can't find much about batching.
Currently using "#apollo/client#^3.0.2"
Here's my client set up.
import { ApolloClient, InMemoryCache, ApolloLink, from } from '#apollo/client'
import { BatchHttpLink } from '#apollo/client/link/batch-http'
import { onError } from '#apollo/client/link/error'
const BASE_URL = 'http://localhost:4000'
const httpLink = new BatchHttpLink({
uri: BASE_URL,
credentials: 'include',
})
const csrfMiddleware = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
'X-CSRF-Token': getCSRFToken(),
},
}))
return forward(operation)
})
const errorMiddleware = onError(({ networkError }) => {
if (networkError && 'statusCode' in networkError && networkError.statusCode === 401) {
window.location.assign('/accounts/login')
}
})
const client = new ApolloClient({
link: from([errorMiddleware, csrfMiddleware, httpLink]),
cache: new InMemoryCache(),
})
This is the react hook I'm trying to console log.
const {data} = useQuery(GET_USER_PERMISSIONS_AND_PREFERENCES)
Figured it out. You need to add another middleware to return the data that the useQuery hook can recognize. The data that comes back in the batch call is an array of objects shaped
{
payload: {
data: { ... }
}
}
So something like this did the trick for me
const batchParseMiddleware = new ApolloLink((operation, forward) => {
return forward(operation).map((data: any) => data.payload)
})
I have been having a similar issue, and have so far only been able to solve it by breaking batching and converting to a normal HttpLink

How to fix TypeError: req.url.toLowerCase is not a function

I'm setting up a service and i want to use a json file with mock data to start with. However i get a TypeError: req.url.toLowerCase is not a function when i use that service with the mock data, how can i resolve this error?
Service:
import mockCompetitions from '../../mocks/competitions-mock.json';
export class CompetitionsService {
constructor(protected http: HttpClient) { }
getCompetitions() {
console.log(mockCompetitions);
return this.http.get(mockCompetitions);
}
}
Component:
competitions: any = [];
constructor(private competitionsService: CompetitionsService) {}
ngOnInit(){
this.getCompetitions();
}
getCompetitions(){
this.competitionsService.getCompetitions().subscribe(data => {
this.competitions = data;
console.log(this.competitions);
}, err => console.error(err), () => console.log('Finished Loading...'));
}
I expect a list of names to be printed out on the page from the json file.
If you want to use httpclient to read local json file, put the json file in assets folder as name-of-the-file.json and make the http request by using assets folder as url. It is important that you put it in the assets folder, so that Angular can find it. So your code should look something like this:
export class CompetitionsService {
constructor(protected http: HttpClient) { }
getCompetitions() {
return this.http.get('./assets/name-of-the-file.json');
}
}
So no need to import the file.
For using json file as a data provider you can use import and require.
import data = require('your_file.json')
console.log("data : ", JSON.stringify(data));
You are using the JSON file as an url to your http.get().
If you want to test your service using mock data, I would recommend some HTTP mocking website, like mocky. Put your JSON file there and use the URL that the site generates for you in your http.get(). You won't have to change anything except that in your code.

Loading local json file into redux store with axios, but it fails after I refresh in another route

So I'm practicing React and Redux, and I'm loading a local json file into the store like this ...
import { LOAD_BOOKS } from "./booksConstants";
import axios from "axios";
export const loadBooks = data => {
return {
type: LOAD_BOOKS,
payload: data
};
};
export const asyncLoadBooks = () => {
return async dispatch => {
const response = await axios.get("books.json");
const data = response.data.books;
dispatch(loadBooks(data));
};
};
And here's the reducer ...
import { LOAD_BOOKS } from "./booksConstants";
import { createReducer } from "../../store/reducerUtil";
const initialState = {
books: []
};
export const loadBooks = (state, payload) => {
return {
...state,
books: payload
};
};
export default createReducer(initialState, {
[LOAD_BOOKS]: loadBooks
});
And I'm connecting the App.js to the store with connect() and firing the 'asyncLoadBooks()' in 'componentDidMount()' like this ...
componentDidMount() {
try {
this.props.asyncLoadBooks();
} catch (error) {
console.log(error);
}
}
And everything is working just fine when I loop over the data and display them, however, if I'm on any other route other than "/" and refresh the app manually it gives me this error Failed to load resource: the server responded with a status of 404 (Not Found)
I tried to move the methods to the constructor instead of 'componentDidMount' but it didn't work.
What should I do here? And please keep in mind that I want to use axios and redux to practice them.
Edit
I put a console.log into each async action creator and apparently when I'm on any route other than the home "/" it tries to get the JSON file from this path and can't find it GET http://localhost:3000/category/books.json 404 (Not Found)
How can I solve this?
Ok, guys, I figured it out, the problem was in axios trying to the fetch the JSON file from different paths when you're on different routes, I fixed that by setting a global default baseURL for axios in the index.js file like this ...
import axios from "axios";
axios.defaults.baseURL = "http://localhost:3000/";
And now you can refresh in any route and the data will be fetched successfully.