Skip to content

Instantly share code, notes, and snippets.

@bootrino
Created April 14, 2020 23:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bootrino/7e062770ed331753f18ce37ebd07fd8c to your computer and use it in GitHub Desktop.
Save bootrino/7e062770ed331753f18ce37ebd07fd8c to your computer and use it in GitHub Desktop.
DjangoRenderFormContext.js
import React, {useState, useEffect, createContext, useContext} from "react";
import debug from 'debug';
import URI from "urijs";
import get from 'lodash.get';
import {StateContextAjaxRequestCache, ProviderAjaxRequestCache} from "./StateContextAjaxRequestCache";
import _ from "lodash";
const log = debug('DjangoRenderFormContext');
export const DjangoRenderFormContext = createContext();
export function useDjangoRenderForm() {
/*
We request the form from Django.
We parse the HTML input fields out of the form and create React elements for each field.
We have JSX that renders the input fields.
On submit, we POST the form to the back end.
We check the HTTP result from the back end.
If 200 all good go ahead
If not 200 display the form back to the user, showing field errors.
*/
const [trigger, settrigger] = useState(false);
const [fielderrors, setfielderrors] = useState(null);
const [renderoutputdata, setrenderoutputdata] = useState(null);
const [httpmethod, sethttpmethod] = useState("GET");
const [postdata, setpostdata] = useState(null);
const [responseDOM, setresponsedom] = useState(null);
const [url, seturl] = useState(null);
const [isloading, setisloading] = useState(false);
const [iserror, setiserror] = useState(false);
const [finalrenderurls, setfinalrenderurls] = useState({});
const {getajaxrequestcache, setajaxrequestcache} = useContext(StateContextAjaxRequestCache);
console.log("getajaxrequestcache");
console.log(getajaxrequestcache);
const ajaxRequestCacheKey = `renderToyEditFormHTML`;
useEffect(() => {
setfielderrors(null);
let xhr = get(getajaxrequestcache, `${ajaxRequestCacheKey}.xhr`, null);
if (xhr !== null) {
if ((xhr.status !== 200) && (xhr.status !== 422)) {
alert(`expected 200 or 422, got ${xhr.status}`);
}
if (xhr.status === 200) {
let djangoRawHTML = xhr.responseText;
let djangoDOM = new DOMParser().parseFromString(djangoRawHTML, "text/html");
const updatednetworkresponses = {...getajaxrequestcache}
if (xhr.status === 422) {
// 422 means field errors
// there should be a div in the response with id "form_field_errors_json"
console.log("422 response: field errors");
try {
let responseText = djangoDOM.getElementById("form_field_errors_json").innerText;
_.set(updatednetworkresponses, `${ajaxRequestCacheKey}.fielderrors`, JSON.parse(responseText));
} catch (e) {
alert(`error parsing response JSON ${e}`);
return;
}
}
_.set(updatednetworkresponses, `${ajaxRequestCacheKey}.processed`, true);
_.set(updatednetworkresponses, `${ajaxRequestCacheKey}.djangoDOM`, djangoDOM);
setajaxrequestcache(updatednetworkresponses);
}
}
}, [get(getajaxrequestcache, `${ajaxRequestCacheKey}.loading`, false)]); // trigger whenever the loading state changes
return {
trigger, settrigger,
fielderrors, setfielderrors,
renderoutputdata, setrenderoutputdata,
httpmethod, sethttpmethod,
postdata, setpostdata,
responseDOM, setresponsedom,
url, seturl,
isloading, setisloading,
iserror, setiserror,
finalrenderurls, setfinalrenderurls,
};
}
export const DjangoRenderFormProvider = ({children}) => {
const {
trigger, settrigger,
fielderrors, setfielderrors,
renderoutputdata, setrenderoutputdata,
httpmethod, sethttpmethod,
postdata, setpostdata,
responseDOM, setresponsedom,
url, seturl,
isloading, setisloading,
iserror, setiserror,
finalrenderurls, setfinalrenderurls,
} = useDjangoRenderForm();
return (
<DjangoRenderFormContext.Provider value={{
trigger, settrigger,
fielderrors, setfielderrors,
renderoutputdata, setrenderoutputdata,
httpmethod, sethttpmethod,
postdata, setpostdata,
responseDOM, setresponsedom,
url, seturl,
isloading, setisloading,
iserror, setiserror,
finalrenderurls, setfinalrenderurls,
}}>
{children}
</DjangoRenderFormContext.Provider>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment