Responsive Multi Step Form (React + TS and SCSS)
Design comparison
Solution retrospective
What are you most proud of?
I like the folder-structure. I enjoyed separating content in "data" modules from rendering "components" on"pages", as well as having my stylesheets in "scss" files. It seems to me well structured and clean. I didn't face any problems losing myself in my own code.
Project Highlights: localStorage and useContext()
I decided to combine "localStorage" with the "useContext - Hook" for user input storage. Simply because 'till now I either worked with JSON-Server or MongoDB. Since I haven't used localStorage for a while now, I thought it'd be a great chance for this project. Then I added the useContext - Hook for sharing the input data between the routes and passing it either forward towards the finishing site, or for going back and updating data. You can look up the browser dev tools "application" for what has been stored inside Local storage. This also hepled me for dev - purposes, so that there's no need to uncommend the required fields of the first page when jumping back to it.
css and sass
I really enjoyed getting my styles done with sass variables.
What would you do differently next time?
***Start with the mobile-first workflow and style the app first, rather than getting both, logic and styles done at the same time.
***Dockerizing my web app.
Found a helpful post on dev.to by Lester Diaz Perez
I found it somehow cumbersome to adapt the container size styling on mobile / desktop version, when i.e. toggling between monthly or yearly plans. Working here and there with fixed widths and browser Inspect tool worked for me. I found working from time to time with the tsx inline styling and ternary operator is a great thing, i.e. toggling between active - inactive classes.
logicworking with ts and localStorage has also led to irritation for me. For example, on the finishing page I get my object saved in localStorage: name: ['Customisable profile']. I had previously selected this on the addons page and it is saved in localStorage with setItem.
When I call getItem on the following finishing page in console.log(typeof getItem("addons")), I get: "object".
If I log console.log(getItem("addons")) I get:
{price: Array(1), name: Array(1)}
name: ['Customisable profile']
price: ['$2/mo']
In order to be able to use it type-safe in my children component and pass it to my parent component, I call the following in my FinishCard, for example:
type FinishCardProps = { getItem: string[] } But I get the following message in vscode: This expression cannot be called. The type "string[]" has no call signatures.ts(2349)
So I continued working with "any" as a transition, but that misses the point of TS, doesn't it? Because getItem is defined as an array of strings in the FinishCardProps type, but I'm trying to use it as a function by calling getItem("addon"), I need to set it to a function in FinishCardProps. But it's still not working with "getItem: (item: string) => void". I'm missing some crucial point...
What specific areas of your project would you like help with?- Actually I wanted to test my web app with jest / react-testing-library, but I think my vite config wasn't setup right. Has someone found a nice article or some other content?
- I'd really like to read some thoughts/advice on how to use TS in this app efficiently.
Community feedback
- @markuslewinPosted 9 months ago
Regarding the types, I think Fully Typed Web Apps does a great job explaining some approaches to these types of problems! The TLDR is that you can use a validation library (like zod) to parse objects you can't know the shape of:
// zod schema const personInfoSchema = z.object({ name: z.string(), email: z.string(), phone: z.string(), }); const PersonalInfoCard = () => { // Read initial state from localStorage const [inputs, setInputs] = useState(() => { try { // Parse string const rawPersonInfo = JSON.parse(localStorage.getItem("person")!); // Parse object const personInfo = personInfoSchema.parse(rawPersonInfo); // const personInfo: { // name: string; // email: string; // phone: string; // }; return personInfo; } catch (error) { console.error("Error setting localStorage:", error); // Default values return { name: "", email: "", phone: "" }; } }); };
Marked as helpful1@CipiVladPosted 9 months agoThanks a lot @markuslewin this is a great piece of advice! And the link you shared is really well. You're my mentor of the week :)
1
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord