简体   繁体   中英

trying to get config from backend to react front-end

Am trying to make a script that easy to edit for users from the back-end, so they won't need to re-build the react app each time they edit something (such as color, phone number etc) so i make a call to the back-end by axios

let config={};
(async () => {
  try {
    config = await axios.get("http://localhost:8000/settings");
    config = config.data;

    } catch (e) {
      alert(e);
  }
})();

const App = () => {

  let show;
  ///
  const [name, setName] = useState("");
  const [inchat, setInchat] = useState(false);
  const { t, i18n } = useTranslation();
  ///settings
  const [direction, setDirection] = useState("text-left");
  const [socket] = useState(openSocket(config.url || '/'));
  console.log(socket)
  const [settings] = useState(config);

as you see, after loading the config file from back-end, am using it here in front-end.

the problem is that sometimes the App component load first, and the script throw error of config undefind, how can i make the script http request lunch first, i tried to put the http request inside a useEffect hook but still the same problem. thank you

This is how I usually implement things when it comes to http requests.

This is assuming that you're not using Server Side Rendered (SSR) service like Next.js, where you want the data to be fetched before the page is even rendered, then you would use a different approach.

Otherwise you could show a loading animation or just show a blank screen until the data is loaded.

Click the "Run code snippet" button below to see it work.

 // main.js const { useState, useEffect } = React; const App = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [data, setData] = useState(null); useEffect(() => { /* StackOverflow not letting me do async/await so doing a promise */ fetch('https://jsonplaceholder.typicode.com/todos/1').then(response => response.json()).then(json => { setData(json); setLoading(false); }).catch(error => { console.log('ERROR', error); setError(error); setLoading(false); }); }, []); return <div> {loading? <p>Loading...</p>: <div> {error? <div>{JSON.stringify(error)}</div>: <div>Loaded <br />{JSON.stringify(data)}</div> } </div>} </div> } ReactDOM.render(<App />, document.querySelector('#root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

Since the call to your API is async you will need to wait for the call to be finished to show your app, useEffect is a good way to do it, but you will need to make some changes in your code to work.

I see that you are handling all the state variables separately but some of them depend on each other, for this cases is better to use an object so you can be sure all the properties are updated at the same time and also to know if you have already the needed data to show your app

// show your app until this is not null
const [state, setState] = useState(null);

// set all the state variables at the same time
useEffect(() => { axios.get(url).then(config => setState(config)) }) 

if(!state) return <div>Loading...</>

return <div>App</div>

Another alternative is to use another state variable to control if you should show your app or not

// all your state variables
const [state, setState] = useState(null);
.
.
const [isLoading, setIsLoading] = useState(false);

// set all the state variables at the same time
useEffect(() => { 
  setLIsLoading(true); 
  axios.get(url).then(config => {
    setIsLoading(false);
    setState(config);
  )
}) 

if(isLoading) return <div>Loading...</>

return <div>App</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM