Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found
Not Found

All comments

  • @SoulRvr29

    Submitted

    It was easy, but a good challenge. It's the first time I've combined React with Tailwind and I'm happy with the result. I'm still not entirely sure how data fetch works, but I managed to get it done.

    @fazzaamiarso

    Posted

    Hi @SoulRvr29! Great work on your project, the README is fantastic!

    You can use 1 state for this project. Example

    // `advice` become an object
    const [advice, setAdvice] = useState({});
    
    // then you can get the advice data
    const adviceContent = advice.advice;
    const adviceId = advice.id
    
      useEffect(() => {
        clickHandler();
      }, []);
    
      const clickHandler = () => {
        fetch("https://api.adviceslip.com/advice")
          .then((response) => {
            if (response.ok) {
              return response.json();
            } else {
              console.log("no data");
            }
          })
    
          .then((data) => {
            setAdvice(data.slip)
          })
    
          .catch((err) => {
            console.log("Something went wrong!", err);
          });
      };
    

    I hope it helps! Cheers!

    Marked as helpful

    1
  • Sam 940

    @JustANipple

    Submitted

    Hi everyone! i made it through this challenge!

    The hardest part was to manage states for every component and passing everything to the "add to cart" button to fill the cart list

    Hope you will like it!

    I would like to get any tip on how to improve my solution!

    @fazzaamiarso

    Posted

    Hi Sam! Great job on completing the project!

    I have a quick tip for you.

    The vote state is excessive because you can derive the Vote value from the cart's quantity. Here's how

    // `cart` is cartItems and `setCart` is setCartItems
    const Vote = ({ cart, setCart }) => {
      function handlePlusClick() {
    // increment the quantity directly
        setCart((prevCart) => ({ ...prevCart, quantity: prevCart.quantity + 1 }));
      }
    
      function handleMinusClick() {
        if (cart.quantity <= 0) return;
    // decrement the quantity directly
        setCart((prevCart) => ({ ...prevCart, quantity: prevCart.quantity - 1 }));
      }
    
      return (
        <div className={styles.container_vote}>
          <button className={styles.vote_plus} onClick={handleMinusClick}>
            <img src="icon-minus.svg" alt="downvote" />
          </button>
          <p className={styles.vote_score}>{cart.quantity}</p>
          <button className={styles.vote_minus} onClick={handlePlusClick}>
            <img src="icon-plus.svg" alt="vote" />
          </button>
        </div>
      );
    };
    

    I hope it helps you! Cheers!

    Marked as helpful

    0
  • Bryan Li 3,530

    @Zy8712

    Submitted

    Very fun project. Hoping to get some advice with localstorage and how I can use things such as .env, backend api's, etc in order to protect API Key's and other various things. Thanks.

    @fazzaamiarso

    Posted

    Hi @Zy8712! Nice solution!

    Since you use Vercel to deploy your project, you can take a look at Vercel Serverless function to create a simple API endpoint which have access to Environment Variable. Documentation Reference.

    I also highly recommend you to use a bundler like Vite for your projects.

    I hope it helps! Cheers!

    0
  • P

    @outerpreneur

    Submitted

    My second project with tailwindss how do you do grid template areas with Tailwind CSS? This is the only way I have found out. The slider has a working solution at the moment but is not yet perfect

    @fazzaamiarso

    Posted

    Hi @outerpreneur!

    I think Tailwind doesn't have support for grid template area. If you really want to do it with template area, then you may have to resort to write custom CSS. Docs reference.

    Cheers!

    Marked as helpful

    0
  • MrDannie 50

    @MrDannie

    Submitted

    Hi guys!👨‍💻 I'm super exited completing this challenge! I've a learnt a whole lot as this is first largest app I have built using React and Tailwind (I have always been an Angular developer). I encountered a lot of challenges, bugs and errors in the process of developing this application, which I learnt a lot from. And also thanks to Google, youtube & stack overflow, I would probably had been stuck on some errors forever 😂 :)

    Some of major areas I encountered challenges while developing this application were State Management & Passing data btw components. However I believe was able to do a good Job at this as it pushed me to learn how to effectively utilize tools like Context Api, useRef, useEffect, props and callback.

    I will love to receive feedbacks from the community :

    • How long did it take you to complete this project (it took me 1 and half month)?
    • What was the biggest thing you learnt building this project?
    • What were your most difficult areas?

    Pls kindly also rate my work on a scale of 1-10, I would be also pleased to know what areas I should in improve on?

    Thanks! 😊

    @fazzaamiarso

    Posted

    Hi @MrDannie! It's awesome that you complete this complex project while learning a new framework!

    I just have a couple suggestions for you:

    • I noticed that you use react-hooks-global-state for Global State. I suggest to take a look at Jotai which do the same thing and same maintainer, but still active and maintained.
    • For some side-effects like inserting item into LocalStorage, it's better to first do it inside Event Handler, rather than useEffect that can be tricky to track. You can refer to this docs. For example in App.jsx
    // instead of this
    useEffect(() => {
        localStorage.setItem("BoardData", JSON.stringify(boardData));
      }, [boardData]);
    
    // do this
      const updateAppData = (data) => {
        setAppBoardData(data);
        // here, what trigger the side effect is immediately obvious
         localStorage.setItem("BoardData", JSON.stringify(data));
      };
    

    I hope it helps! Cheers!

    Marked as helpful

    0
  • @fazzaamiarso

    Posted

    Hi ! Nice Solution!

    I have some quick tips for you

    • For deleting item, you can use .filter to avoid array mutation.
    const handleDeleteItem = (itemToDelete) => {
        const updatedItems = selectedItems.filter(item => item !== itemToDelete)
        setSelectedItems(updatedItems);
        setFilterVisible(updatedItems.length !== 0)
      }
    
    • You can utilize spread operator to pass props to a component if the props is the same as the object. Example
    // instead of this
                <Jobs
                  key={job.id}
                  id={job.id}
                  company={job.company}
                  logo={job.logo}
                  new={job.new}
                  featured={job.featured}
                  position={job.position}
                  role={job.role}
                  level={job.level}
                  postedAt={job.postedAt}
                  contract={job.contract}
                  location={job.location}
                  languages={job.languages}
                  tools={job.tools}
                  openFiltered={handleOpenFilter}
    
    // more concise, with the tradeoff of must lookup `job` to know what you passing
    <Jobs key={job.id}  {...job} openFiltered={handleOpenFilter} />
    

    I hope it helps! Cheers!

    Marked as helpful

    0
  • @Leone-Ricardo

    Submitted

    In this challenge, I changed some parts to make it as professional as possible, and one of the features I added was the success message that appears after completing the registration, it was not in the original documentation, but I thought it would look more stylish this way haha. Better solutions and tips are always welcome!

    @fazzaamiarso

    Posted

    Hi @Leone-Ricardo! Nice solution and great addition!

    I have some suggestion for you

    • For Submit Button, it's better to use a <button> as it can have image, icons, elements, and text as a display value, whreas <input> can only have text as value. So it become
    // <button> by default have "submit" type
     <button id="formSubmit" class="btn_submit">Claim your free trial</button>
    
    • If you implemented the suggestion above, then you can also refactor the inputs looping like this.
    // select all input elements
     const inputElements = document.querySelectorAll("input");
    
    // loop all input with forEach, where `inputEl` is the actual input element
      inputElements.forEach((inputEl, idx) => {
        inputEl.classList.remove("error");
        formError[idx].style.display = "none";
    
    //... other codes
      })
    

    I hope it helps! Cheers!

    1
  • @JaredBrown1

    Submitted

    1. What did you find difficult while building the project?

    What was difficult for me was getting the state in order. I had to really sit back and think about how to get all this state to load in one bigger component. Dark mode was a little struggle as well.

    1. Which areas of your code are you unsure of?

    I am unsure of the way I handled the state of the dark mode toggle button. I want to get it to where it can toggle depending on the users system dark mode settings, if that makes sense because right now it can load in with dark mode but the button isn't toggled.

    3)Do you have any questions about best practices? I would appreciate any advice on best practices regarding the way I handled the state in my application.

    @fazzaamiarso

    Posted

    Hi @JaredBrown1! Great work on finishing your project!

    I think I can help answer your questions:

    1. State management is definitely hard. My recommendation is to read this article by Kent C. Dodds as a starting point. I also encourage you to read his other articles on React because I learnt a lot of best practices from him.
    2. In next-themes, You can get the user's system theme returned by useTheme. Here's the documentation reference. Example:
    const { systemTheme } = useTheme()
    
    useEffect(() => {
    // set toggle state based on user's theme
    }, [])
    
    1. To keep your codebase clean and formatted nicely, you always want to have ESLint combined with Prettier. Here is a simple tutorial

    I hope it helps! Cheers!

    Marked as helpful

    0
  • @fazzaamiarso

    Posted

    Hi @ansman58! Great job on finishing the project!

    I have some suggestions for you

    • Currently you are navigating by rendering component conditionally with State. I recommend you to use a routing library instead. The most popular is React Router
    • In your Crew page, rather than using useEffect to find the selected crew, you can achieve the same result by doing it in render. Example:
    // by doing this, you don't need `data` state anymore
    const { crewMember, setCrewMember } = React.useContext(CurrentNavContext);
    
    // this will be re-calculated everytime `crewMember` changes. 
    const crewInfo = crew.find((item) => item.role === crewMember) ?? null;
    
      <Section
                subtitle={crewInfo?.role}
                title={crewInfo?.name as string}
                description={crewInfo?.bio as string}
                titleClass={style.sectionTitle}
                subtitleClass={style.sectionSubtitle}
              />
    
    

    I hope it helps! Cheers!

    0
  • P
    Andrija 560

    @andrijaivkovic

    Submitted

    Hi! This is my solution to this challenge. Any and all feedback is appreaciated! :)

    @fazzaamiarso

    Posted

    Hi @andrijaivkovic! Great work!

    I have some suggestion for you

    Since this project require you to use an API Key which anyone can exploit if exposed to public (especially paid services). You can utilize Netlify functions in conjuction with environment variables to hide your API Key. Here are tutorials for Netlify Functions and environment variables.

    I hope it helps! Cheers!

    0
  • Gii 310

    @giiancarlonv

    Submitted

    badly need help! i got this error after deploying, did everything to fix it

    error message - Loading module from “https://giiancarlonv.github.io/assets/index-66f0fd8a.js” was blocked because of a disallowed MIME type (“text/html”).

    *edit fixed. thanks everyone!!

    @fazzaamiarso

    Posted

    Hi @giiancarlonv!

    I've taken a look at your code and I suspect it's because of the Script tag in index.html that contains the attributes below which not suppose to be there

    type="module" src="https://giiancarlonv.github.io/assets/index-66f0fd8a.js"
    

    I hope it helps! Cheers!

    1
  • @fazzaamiarso

    Posted

    Hi @suhjiwon95! Great work!

    I have some quick tips for you

    • To improve user experience, you can fetch an initial advice so the UI doesn't feel empty. You can also insert an Empty State UI.
    • When naming in Javascript, especially Frontend, it's primary convention is to use camelCase. If I'm not mistaken, snake_case is Python's convention.
    const advice_id = data.slip.id; 
    
    const adviceId = data.slip.id; 👍
    
    • You can also do Object destructuring.
     const { advice } = data.slip;
    

    I hope it helps! Cheers!

    Marked as helpful

    0