Looking for some help to understand what is going on here.
The Problem
We are using a translation service that requires creating JSON resource files of copy, and within these resource files, we need to add some specific keys that the service understands so it knows what should and should not be translated.
To do this as simple as possible I want to import JSON files into my code without them being tree shaken and minified. I just need the plain JSON file included in my bundle as a JSON object.
The Solution - or so I thought
The developers at the translation service have instructed me to create a webpack rule with a type of assets/source to prevent tree shaking and modification.
This almost works but the strange thing is that the JSON gets added to the bundle as a string like so
module.exports = "{\n \"sl_translate\": \"sl_all\",\n \"title\": \"Page Title\",\n \"subtitle\": \"Page Subtitle\"\n}\n";
This of course means that when I try and reference the JSON values in my JSX it fails.
Test Repo
https://github.com/lukehillonline/nextjs-json-demo
NextJs 12
Webpack 5
SSR
Steps To Reproduce
Download the test repo and install packages
Run yarn build and wait for it to complete
Open /.next/server/pages/index.js to see the SSR page
On line 62 you'll find the JSON object as a string
Open .next/static/chunks/pages/index-{HASH}.js to see the Client Side page
If you format the code you'll find the JSON object as a string on line 39
Help!
If anyone can help me understand what is going wrong or how I can improve the webpack rule to return a JSON object rather than a string that would be a massive help.
Cheers!
The Code
next.config.js
module.exports = {
trailingSlash: true,
productionBrowserSourceMaps: true,
webpack: function (config) {
config.module.rules.push({
test: /\.content.json$/,
type: "asset/source",
});
return config;
},
};
Title.content.json
{
"sl_translate": "sl_all",
"title": "Page Title",
"subtitle": "Page Subtitle"
}
Title.jsx
import content from "./Title.content.json";
export function Title() {
return <h1>{content.title}</h1>;
}
pages/index.js
import { Title } from "../components/Title/Title";
function Home({ dummytext }) {
return (
<div>
<Title />
<p>{dummytext}</p>
</div>
);
}
export const getServerSideProps = async () => {
const dummytext = "So we can activate SSR";
return {
props: {
dummytext,
},
};
};
export default Home;
I am a little confused about how to go about this. So I have this JSON file called posts.json.
[
{
"id": 1,
"title": "Kylie Jenner",
"content": "Social Media Public Figure",
"disclaimer": "*Disclaimer: This user may have comment filtering turned on",
"slug": "hello-world",
"img" : "https://ilarge.lisimg.com/image/16801290/1080full-kylie-jenner.jpg",
"banner" : "https://i.pinimg.com/originals/a5/2b/96/a52b963809c7e64e538b113cccf61dda.jpg",
"handle": "kyliejenner",
"handlelink" : "https://www.instagram.com/kyliejenner/"
}
]
I am currently trying to make a GET request to an API(url) that also includes specific data from my json file. In this case it will include the celebs handle. This is what I have setup here on Graphs.js.
export default class Graph extends Component {
constructor(props) {
super(props);
}
state = {
handle: '',
}
componentDidMount() {
axios.get('http://localhost:5000/celebs/' + handle)
.then(response => {
this.setState({ celebs: response.data })
})
.catch((error) => {
console.log(error);
})
}
}
I am aware this isn't right as this is where I am stuck. "+ handle" is to come from the json file. I want to make a request to the url where /handle will match the handle directly from json file as defined "handle": "#kyliejenner". But I keep getting an error saying 'handle' is not defined no-undef. No matter how I do it, I can't seem to get it right and keep getting the same error.
So how do I go about defining handle with the data from the json file passed into it? More specifically the handle data.
I apologize in advance if this isn't clear. Please let me know if you need further clarrification.
You can store the json in a different file assign the data to an object and you can import it like this.
import posts from 'posts.js';
Now you have access to the posts object in your component, so you can just access it using
const handle = posts[i].handle; //pass the index of array(i);
As pointed in the comment by Sean, your local state is a bit wrong. You should declare it like this:
constructor(props) {
super(props);
this.state = {handle: ''};
}
And use it like this:
axios.get('http://localhost:5000/celebs/' + this.state.handle)
Or, using Template Literals:
axios.get(`http://localhost:5000/celebs/${this.state.handle}`)
More info in the docs: https://reactjs.org/docs/state-and-lifecycle.html#adding-local-state-to-a-class
I am new to node.js and react but I love gatsby.js. I have followed all the tutorials that I can find and it's such a great tool.
However one of the main reasons why I want to use it is I have a file json with 1000 different records in and I would like to generate a new page for each record.
I believe I have come to the conclusion that I need to learn more about the gatsby-node.js file and am aware of the following resource but are there any tutorials or other examples on this topic that maybe a little easier to follow:
https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating-pages-in-gatsby-nodejs
The example you were referring to should already give you a good idea. The basic concept is to import the JSON file, loop over it and run createPage for each of the items in your JSON source. So given an example source file like:
pages.json
[{
"page": "name-1"
}, {
"page": "name-2"
}]
You can then use the Node API to create pages for each:
gatsby-node.js
const path = require('path');
const data = require('./pages.json');
exports.createPages = ({ boundActionCreators }) => {
const { createPage } = boundActionCreators;
// Your component that should be rendered for every item in JSON.
const template = path.resolve(`src/template.js`);
// Create pages for each JSON entry.
data.forEach(({ page }) => {
const path = page;
createPage({
path,
component: template,
// Send additional data to page from JSON (or query inside template)
context: {
path
}
});
});
};
I'm just starting out and have gone through the Vue guide. I've got some basic grasp on imports and exports of ES6 but wanted to know the ideal way of doing this.
I'll have several components that need an original single source of data that i'll need to individually manipulate from there. Ideally I want that data to be in a separate file so that others can manipulate it.
I can figure out to do this via jquery ( seen below ) but I don't really need to make a call as the json file will be internal:
module.exports = {
data: function () {
return {
msg: 'hello',
whatever : 'hi'
}
},
created : function() {
this.fetchData();
},
methods : {
fetchData : function() {
console.log("WORKING");
var self = this;
$.get( apiURL, function( data ) {
self.items = data;
console.log(data);
});
}
}
}
But I also don't want to have all the data be in the App.vue file. I need it somewhere else and then need it to replace my data.
Is the best way to do this to create another Vue file with no template or styling and just create it's own module.exports data object? Say mydata.vue:
module.exports = {
data: function () {
_mydata = {
items : [
{case:'caseone'},
{case:'casetwo'}
],
otheritems : [
{case:'caseone'},
{case:'casetwo'}
]
}
}
}
And then somehow replacing this data object in mydata.vue with the data object in app.vue with imports ( main. js ) ?
import Vue from 'vue'
import App from './App.vue'
import Data from './SiteData.vue'
Just wanted to check if this was the ideal way/i'm on the right path...or if there is an easier way to have a central data object in a different file for all my components?
What I have done is to manage my data in a json file. I think that the approach of use separate files for initial data is cool for small apps. Bigger apps need something more usefull like Vuex.
I don't think it is a good idea to manage a .vue file, as those files are meant to be handled by some module budled system, with the correspondind vue transformation, not the case of the data object.
My approach was this: I had a data.json file
data.json
{
"component1": {
"someData": "someValue",
...
},
...
"componentN": {
"someOtherData": "someOtherValue"
}
}
And then I import that data in the corresponding component
componentN.vue
<template>
</template>
<script>
import { componentN } from './data.json'
export default {
data () {
return componentN
}
}
</script>
Note that:
I used a single file for manage data, however you can split it in a file for every component, for example.
As you can see, this approach can become a mess with medium apps, I don't want to even imagin it in big apps, so be careful.
I'm very new to anything much code related, but I'm on a slow and sometimes painful learning curve.
I have a file containing some json which I read into node.js parse and push to a web socket. The script works fine, but I only ever get one json object returned.
devices.json: (Complete file) Not every element has the same data contents, and there is any number of element objects within a data source.
{
"element":"SENS01",
"data":{
"type":"SEN",
"descr":"T100"
},
"element":"SENS02",
"data":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
},
"element":"SENS03",
"data":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
},
"element":"LED1",
"data":{
"type":"LED",
"state":"0"
}
}
The code which does the stuff is;
server.js:
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs');
// creating the server ( localhost:8000 )
app.listen(8000);
// Server started - load page.
function handler(req, res) {
fs.readFile('/var/www/html/dashboard.html', function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading web page');
}
res.writeHead(200);
res.end(data);
});
}
// creating a new websocket.
io.sockets.on('connection', function (socket) {
console.log();
// 1st READ of json state file.
fs.readFile('devices.json', 'utf8', function (err, data) {
if (err) throw err;
// Parse/check its valid json.
var dump = JSON.parse(data);
socket.volatile.emit('MAP.room1', dump);
});
});
When I connect to the socket the following is sent (as logged from the server console)
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"LED1","data":{"type":"LED","state":"0"}}]}
I never get any of the other objects, only this one. I've had a look round the net about how to iterate over objects, but it was all largely meaningless to me :(
What I am trying to achieve is when you connect to the web socket every object from the devices.json file is pushed out 1 object at a time. So once this is working I would expect to see;
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"LED1","data":{"type":"LED","state":"0"}}]}
debug - websocket writing 5:::{"name":"MAP.room1","args":[{"element":"SENS03","data":{"type":"SEN","descr":"T000:","uid":"X1A1AB","check_on":"2014/06/29"}}]} etc...
If I put a console.log(data) line in my server.js then I see the entire file as expected. Its only once its been parsed am I left with the 1 entry.
Can anyone please explain what's going on, and how I can best overcome this. It needs to be in a really simple way ideally using my own code/dataset as examples so I can understand 'what this means for me' A lot of the web examples and stuff I read tend to use different examples which just confuses me. I know the basics of declaring variables etc, and have an extremely limited experience with Ruby with a simple script to parse some push data received from an API but that's about it.
If you need any more context etc then please let me know, otherwise any help gratefully received.
I think your problem is that you're using the same keys in your JSON. When the parser reads in that JSON, it continuously overwrites previous values of element and data and since those are the only unique key names, those are the only two values you see.
If you modified your JSON so that the same key names are not used on the same "level," then you would see all of the data you are expecting. Here's an example that makes it easy to iterate through each element:
[
{
"element":"SENS01",
"data":{
"type":"SEN",
"descr":"T100"
}
},
{
"element":"SENS02",
"data":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
}
},
{
"element":"SENS03",
"data":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
}
},
{
"element":"LED1",
"data":{
"type":"LED",
"state":"0"
}
}
]
Or if you can guarantee that the element values are always unique, then perhaps you could also do this:
{
"SENS01":{
"type":"SEN",
"descr":"T100"
},
"SENS02":{
"type":"SEN",
"descr":"T088",
"uid":"X1A1AA",
"check_on":"2014/06/29"
},
"SENS03":{
"type":"SEN",
"descr":"T000:",
"uid":"X1A1AB",
"check_on":"2014/06/29"
},
"LED1":{
"type":"LED",
"state":"0"
}
}
Ok so I found out my data was actually JS objects represented as below in a flat format with every object seperated with a linefeed.
{"SENS01":{"type":"SEN","descr":"T100"}
{"element":"LED1","data":{"type":"LED","state":"0"}
Using linereader (from npm) I was able to read the file in by doing;
lineReader.eachLine('simple.txt', function(line) {
var dump = JSON.parse(line);
socket.emit('MAP.room1', dump);
});
That then output the required data from the web socket.