5

I know this question maybe exist in stack overflow but I didn't get any good answers, and I hope in 2020 there is better solution.

In my react app I have a config JSON file, it contains information like the title, languages to the website etc.. and this file is located in 'src' directory

 {
  "headers":{
    "title":"chat ",
    "keys":"chat,asd  ,
    "description":" website"
  },
  "languages":{
    "ru":"russian",
    "ar":"arabic",
    "en":"English"
  },
  "defaultLanguage":"ru",
  "colors":{
    "mainColor":"red",
    "primary":"green",
    "chatBackGround":"white"
  }
}

I want to make my website easy to edit after publishing it, but after I build my app, I can't find that settings.json file there in build directory.

I find out that files in public directory actually get included to build folder, I tried to put my settings.JSON in public, but react won't let me import anything outside of src directory

I found other solutions like this one but didn't work https://github.com/facebook/create-react-app/issues/5378

Also I tried to create in index.html a global var like (window.JSON_DATA={}), and attach a JS object to it and import it to App.js, but still didn't work.

How can I make a settings JSON file, and have the ability to edit it after publishing the app?

1
  • You might be able to load the file at runtime using fs instead of including it. Commented Jun 4, 2020 at 0:54

4 Answers 4

9

Add your settings.json to the public folder. React will copy the file to the root of build. Then load it with fetch where you need it to be used. For example if you need to load setting.json to the App.js then do the next:

function App() {

    const [state, setState] = useState({settings: null});

    useEffect(()=>{
        fetch('settings.json').then(response => {
            response.json().then(settings => {
                // instead of setting state you can use it any other way
                setState({settings: settings});
            })
        })
    })
}

If you use class-components then do the same in componentDidMount:

class CustomComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {settings: null};
    }

    componentDidMount() {
        fetch('settings.json').then(response => {
            response.json().then(settings => {
                this.setState({settings: settings});
            })
        })            
    }
}

Then you can use it in render (or any other places of your component):

function App() {

    ...

    return (
        {this.state.settings && this.state.settings.value}
    ) 
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you , i have one more question, is it bad to put this fetch code outside the component? am now doing this (async ()=>{ try{ settings = await axios.get("config.json"); settings = settings.data; socket = openSocket(settings.url); }catch(e){ settings = fallBackSettings; alert(e) } })() const App =() =>....
@Mohamad Alasly putting the fetch code inside of a component makes you sure that json will be loaded after component is ready. But if you don't warry about it you can place the code wherever you need it. It's up to your requirements.
0

The easiest way would be to require() the file on the server during server side rendering of the html page and then inline the json in the html payload in a global var like you mentioned window.JSON_DATA={}. Then in your js code you can just reference that global var instead of trying to use import.

Of course this approach would require you to restart your server every time you make a change to the json file, so that it get's picked up. If that is not an option then you'll need to make an api call on the server instead of using require().

4 Comments

Just as a heads up, storing values to window like that is a huge XSS vulnerability.
Only if the content is coming from user input and only if you don't sanitize it properly. In this case he is the only one setting the json so there is no risk.
You haven't seen the rest of the code base, so yes, there is a risk. But in general it is a bad practice
There's absolutely nothing wrong with it if the content is coming from a trusted source or properly sanitized. Many popular frameworks suggest this very approach redux.js.org/recipes/…
0

You may want to look at using npm react-scripts (https://www.npmjs.com/package/react-scripts) to produce your react application and build. This will package will create a template that you can put your existing code into and then give you a pre-configure build option that you can modify if you would like. The pre-configured build option will package your .json files as well. Check out their getting started section (https://create-react-app.dev/docs/getting-started/)

If you don't want to go that route, and are just looking for quick fix, then I would suggest change your json files to a JS file, export the JS object and import it in the files you need it since you seem to be able to do that.

//src/sampledata.js
module.exports = {
  sample: 'data'
}
//src/example.jsx (this can also be .js)
const sampledata = require('./sampledata');
console.log(sampledata.sample); // 'data'

2 Comments

Thank you i will try the first option, but what is the benifets of doing JS insted of JSON because i won't find it in the build folder , and this is my main issue, that i can't find my settings.JSON or JS file in build .
There isn't an advantage, I though you were still seeing JS files in the build folder (even though you werent seeing JSON files). Utilizing react-scripts is probably the best route. Despite the landing page for the npm package, there is actually a lot of documentation around the package.
0

you can use 'Fetch Data from a JSON File' according to link https://www.pluralsight.com/guides/fetch-data-from-a-json-file-in-a-react-app example

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.