skip to Main Content

I’m creating a draw.io like design website. I have one component for saved designs and one for the editor/designer.

In the saved designs component, I have a ‘open new file’ button that posts the new file and then navigates to the url with that file ID.

const openNewFile = () => {
    const fileObj = generateDefaultFileObj();
    axios.post(`http://localhost:8000/api/files/`, fileObj);
    navigate(`/file/${fileObj.fileID}`);
}

In the design editor component, when I try get the file that was just posted, I’ll often get an error because its trying to access it before its available. I understand I could just wait for the API post before navigating to the file in the previous component but the downside here is that the user has no immediate feedback that something is being done. There is a half second delay before anything happens, I’d rather present the user the loading screen in the Editor component.

const Editor = () => {
    let { file } = useParams();
    const [isLoading, setLoading] = useState(true);
    const [fileData, setFileData] = useState();
    const [activeObjects, setActiveObjects] = useState([]);
    

    React.useEffect(() => {
        const filePromise = axios.get(`http://localhost:8000/api/files/${file}/`);
        const objectsPromise = axios.get(`http://localhost:8000/api/ro/file/${file}/`);

        Promise.all([filePromise, objectsPromise]).then(([fileResponse, objectsResponse]) => {
            setFileData(fileResponse.data);
            setActiveObjects(objectsResponse.data);
            setLoading(false);
        })

    }, []);

    if (isLoading) {
        return <div>Loading...</div>;
    }

    return (
        <div>Main Component</div>
    )
};

What would be the best way to resolve this?

2

Answers


  1. You can use async/await like this to wait for it end all the calls

    React.useEffect(async () => {
       ...
       await Promise.all(...)
       ...
    })
    
    Login or Signup to reply.
  2. Here’s an updated implementation of openNewFile:

    const openNewFile = async () => {
          const fileObj = generateDefaultFileObj();
          const response = await axios.post(`http://localhost:8000/api/files/`, fileObj);
          const newFile = response.data;
          navigate(`/file/${newFile.fileID}`);
          return newFile;
        };
    

    And here’s how you can modify the Editor component to use the returned file object:

    const Editor = () => {
      let { file } = useParams();
      const [isLoading, setLoading] = useState(true);
      const [fileData, setFileData] = useState();
      const [activeObjects, setActiveObjects] = useState([]);
    
      React.useEffect(() => {
        const getFileData = async () => {
          try {
            const fileResponse = await axios.get(`http://localhost:8000/api/files/${file}/`);
            const objectsResponse = await axios.get(`http://localhost:8000/api/ro/file/${file}/`);
            setFileData(fileResponse.data);
            setActiveObjects(objectsResponse.data);
          } catch (error) {
            console.error(error);
          } finally {
            setLoading(false);
          }
        };
        getFileData();
      }, [file]);
    
      if (isLoading) {
        return <div>Loading...</div>;
      }
    
      return <div>Main Component</div>;
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search