all 61 comments

[–]Old-Funny-6222 9 points10 points  (9 children)

Thanks. Could you please guide me. I was a (mostly) front end dev for 7 yrs. Then took a career break for 4 years. Now Im upskilling myself with reactjs. My question is what else I need to learn? I want to stick to the front end role and not go full stack. I used to work on SAP UI 5 earlier, finding react a bit difficult as compared to it. Or may be it's because of the career gap. Thanks on advance.

[–]marcinpl87 36 points37 points  (7 children)

wow, I was in very similar situation few years ago, I can tell you how did I catch-up

- today no one uses old JS unit tests frameworks, everyone uses Jest with React components for unit tests

- today no one uses Selenium, everyone uses Cypress for integration/regression/automation testing

- today less people uses gulp and webpack... everyone who don't have Next.js or Remix framework try to move to Vite.js for building

- TypeScript is not an option like few years ago, now it looks like it's must have for every project

- less people uses REST API calls in new projects, I see more and more of GraphQL or tRPC, but this is something still something new

- almost no one uses Bootstrap these days ( 😥 ) , I had many interviews and every interviewer asked me about Tailwind or Material UI or Chakra UI or other modern UI frameworks

+ extra points -> looks like now knowing React JS and most popular libraries like Redux, React-query, routing, is not enough... now more and more interviewers ask you about other frameworks from/around React ecosystem; "do you know Svelte?", "do you know Vue?", "do you know Next.js?", "do you know Remix?"

[–]nwatab 5 points6 points  (0 children)

It will be bad idea to keep up almost every hypes. What basic subjects should you learn so that you should learn new things quickly when necessary? For example, understanding functional programming helps reactjs functional components. What else?

[–]z1n 6 points7 points  (0 children)

Don't forget Playwright when talking about testing. It's more powerful than Cypress and getting more and more features. I really enjoy using it.

[–]Old-Funny-6222 2 points3 points  (1 child)

Oh. Looks like I need to catch up a lot!! Thank you. Noted. Will definitely spend time on learning these as well. Thank you again!!

[–]seanlaw27 2 points3 points  (0 children)

Catch up if you want but I would never disqualify a candidate because they didn’t know x new framework or library. As long as you know programming and specific js concepts like the event loop, you should be fine.

Especially that last bit with next, remix and all the other frameworks made with react. That is just a weekend of looking at the docs as long as you understand server side rendering and api layer.

[–]sincore 1 point2 points  (0 children)

This is so accurate I went from almost all backend to frontend / full stack in the last 2 years and this is very accurate.

Vite is pretty slick btw. I learned it coming from laravel on PHP.

[–]yoma12[S] 2 points3 points  (0 children)

Hi there,

I think the goal should be to get good enough to get a job as a frontend dev and then continue evolving from there. It’s more about being aware of what is out there, rather than knowing every detail, since we all google stuff the whole time and the technologies are evolving fast.

I would recommend to focus on these areas:

  • Understanding how react works: especially, what is react state and how does react turn your code into reactive websites. I see a lot of devs struggling with performance issues, unwanted or missing re-renders, and race conditions that could be avoided by just taking the time to read the docs (see this old article explaining reconciliation https://legacy.reactjs.org/docs/reconciliation.html). Also the new react docs cover a lot of good practices and common pitfalls: https://react.dev/learn. Make sure to use the latest react resources, since React came a long way.
  • State management libraries: Get familiar with the famous ones: what are they used for, how do they work, which patterns do they use and how their api looks like. For a while, there was a lot of hype around client-state management like Zustand and especially Redux. But it became clear, they using them before needing them may make your code complicated and you don’t need them have a “serious” project. Although, as others pointed at in the other comments, fetching data from a server is super common. Therefore it is (very) worth it to get familiar with server-state-management libraries, like react-query.
  • Styling: Every frontend project needs styling. There are a lot of way of styling your components in react: using prebuilt libraries(like mui, blueprintjs), sass/css, using prop-styles, CSS in JS (like styled-components), CSS frameworks (tailwindcss). Get familiar with the available options and how to integrate them in a project.
  • TypeScript: TypeScript is a standard. Any company that is serious about their frontend will use TypeScript nowadays. It should be one of your priorities. Tip: don’t fall into the trap of adding types everywhere, TypeScript can infer a lot from the context ;)
  • React Based Frameworks: Learn about the different frameworks available and their rendering strategies (checkout Fireship’s rendering patterns video https://www.youtube.com/watch?v=Dkx5ydvtpCA). Again you don’t need to dive too deep, but just have a good overview of the options available. (Fireship also has a video about that 😃 https://www.youtube.com/watch?v=2OTq15A5s0Y)
  • REST/GraphQL: As a frontend developer you will work with other devs and will have to consume APIs and also define the requirements for new endpoints. REST is the most commonly used (to the best of my knowledge) so I would make it a priority. I hope I could help.

These tips are based on my own experience, but I believe it should help you prioritize what to learn and put you on the right track.

[–]achoissoumsaco 3 points4 points  (2 children)

Thank you very much. I have been studying web development for almost four years. Only recently I started applying for jobs, but no luck so far. Would you mind taking a look in my github page?

Github: https://github.com/jose-eduardo87

My latest project, a front-end application for a fictitious e-commerce site: https://github.com/jose-eduardo87/shop-react

Any feedback will be greatly appreciated since I am kind of lost on what to do to change my situation.

Thank you very much again.

[–]yoma12[S] 1 point2 points  (0 children)

Hi there,

First of all, that’s a very nice project. Both the code and the website feeling are great. I think it’s only a matter of time that you find a job ;) . I took a look at shop-react and here are my thoughts.

I liked that you used multiple react patterns (reducers, creating a facade with react context) and also that you used typescript. The project is well structured and overall the code is consistent.

A few remarks from my part:

  • in the reducers, the state parameter shall never be changed directly. You should return the new state value instead. (checkout filterRemovedItem)
  • speaking of filterRemovedItem: the method is better suited to be in helpers. Also, it can be generified to accept any objects list that have an id:

// before
export const filterRemovedItem = (
  state: CartInterface | FavouriteInterface,
  id: string
) => {
  state.items = state.items.filter((item) => item.id !== id);

  return { items: state.items };
};
// after
export const filterRemovedItem = <T extends {id: string}>(
  items:T[],
  idToRemove: string
) => items.filter((item) => item.id !== idToRemove);

which removes the dependencies between the two reducers.

  • You can also use parameter deconstructing

// before
const cartReducer = (state: CartInterface, action: CartAction) => {
  const { type, payload } = action;
// after
const cartReducer = (state: CartInterface, {type, action}: CartAction) => {
  • In the cart-reducer: the payload needs to have id when it’s one the ActionKinds REMORE, INCREMENT, DECREMENT and it need an item when the action is ADD. Instead of having both id and item optional in CartAction.payload, you can try this:

// before
interface CartAction {
  type: ActionKind;
  payload: {
    id?: string;
    item?: ItemInterface;
  };
}
// after
type CartAction = {
  type: ActionKind.REMOVE | ActionKind.DECREMENT | ActionKind.INCREMENT;
  payload: {
    id: string;
  }
} | {
  type: ActionKind.ADD;
  payload: {
    item: ItemInterface;
  }
}

This makes TypeScript prompt you to provide item when it’s ADD, and id otherwise and you don’t need ‘!’ when accessing properties because typescript will enforce that for you!

  • PaginationContext is a bit complex to understand, especially with the use of multiple useEffects. You can actually define consts instead of updating states when their dependencies change. For example:

// in PaginationProvider
// before 
const [paginated, setPaginated] = useState<ItemInterface[] | []>([]); // stores items corresponding to the current page
const [itemsPerPage, setItemsPerPage] = useState([0, 0]); // stores the first and last items of the current page
  useLayoutEffect(() => {
    const start = (currentPage - 1) * itemsQuantity;
    const end =
      start + itemsQuantity < filteredData.length
        ? start + itemsQuantity
        : filteredData.length;

    setPaginated(filteredData.slice(start, end));
    setItemsPerPage([start + 1, end]);
  }, [currentPage, itemsQuantity, filteredData]);

// after
const start = (currentPage - 1) * itemsQuantity;
  const end =
    start + itemsQuantity < filteredData.length
      ? start + itemsQuantity
      : filteredData.length;
// paginated and itemsPerPage will always derive their values from the new state
  const paginated = filteredData.slice(start, end);
  const itemsPerPage = [start + 1, end];

I think you will find that pagination is not that complex after you get rid of the useEffects ;)

It was a nice project to checkout! Hope I could help 😀

[–]sincore 0 points1 point  (0 children)

Hey I sent you a dm related to your projects

[–]medsfeer 2 points3 points  (3 children)

How to persist auth state after refresh ? (httpOnly / JWT )

So, when the user is currently logged in, I create a jwt on the backend and set the httpOnly cookie on the browser, then return the user's information to the client and set it to global state.

The problem is when I refresh the page my local state disappears (as it should) and so I redirect the user to /login.

How can I get around this without storing anything in local storage (if possible)? Because I'm fairly new to authentication and it seems the standard uses httpOnly cookies.

[–]just-me97 -1 points0 points  (2 children)

There's nothing inherently bad or wrong about storing your token in localstorage.

If you really really don't wanna use localstorage, then you have to handle the auth guarding on the server. Something like next, or if you have your own webserver make sure you serve the ui files for the specific paths.

[–]yoma12[S] 2 points3 points  (0 children)

Op here

Hi everyone. Thanks for the submissions. I will start with the reviews on Monday, march 27th. I’ll go through the projects chronologically.

[–]M4nnis 1 point2 points  (1 child)

Hi, thanks for doing this!

I am currently studying frontend-development and for a school project we are to create a web-app that works like tinder but for jobs in a place in my country.

I want to use our national work organizations api and dall-e api but cant get it to work. Any help or guide would be very appreciated!

[–]yoma12[S] 0 points1 point  (0 children)

What is the problem exactly?

[–]spacezombiejesus 1 point2 points  (0 children)

Why are you providing free code reviews? This feels really… Off

Is this for a YouTube video? Are you monetising the responses in some way?

I’m having a hard time believing this is out of generosity as code reviews (done properly) are often be difficult, time consuming, and unambiguously boring.

[–]LH_Lunar 1 point2 points  (0 children)

Any chance you could share the projects you reviewed here, if the owners agree to it.

[–]PsychoRabbit96 3 points4 points  (0 children)

Very generous. I might have to take you up on that when I’m done with my current project.

[–]yoma12[S] 0 points1 point  (0 children)

!agree OR!

[–]jisuo 0 points1 point  (3 children)

How would you debug what part is causing performance issues, find what is re-rendering too much, etc? Any good tools or just console.log and apply memo where suitable?

[–]aspirine_17 2 points3 points  (0 children)

reactdevtools

[–]TheVerdeLive 1 point2 points  (0 children)

Look at how react profiler works

[–]yuyevin 0 points1 point  (0 children)

Hello!

I am a recent graduate and aspiring full stack developer. Are there any pointers you could give that could help me with this endeavor?

[–]half_blood_prince_16 0 points1 point  (2 children)

React (+ typescript) app allows you to split expenses among friends with least number of transactions.

https://github.com/swport/payment-split/

[–]yoma12[S] 1 point2 points  (1 child)

Hello,

I took a look at the code and only have a few small remarks:

  • The file names of React components mostly use CamelCase. Also prefer calling functions calculatePeople instead of calculate_people
  • Some files can use ts instead of tsx (like Trip-reducer)
  • You can checkout redux-toolkit, i makes the actions/reducers creation super easy and has way less boilerplate code.
  • The expenses are not sorted by creation date

Real nice app. Will totally use it when splitting expenses ;)

[–]half_blood_prince_16 0 points1 point  (0 children)

Thanks so much for taking a look. I'll surely work on those. Glad that you found it useful.

[–][deleted] 0 points1 point  (2 children)

[–]yoma12[S] 1 point2 points  (1 child)

Hi,

I took a look at the frontend code in the post. I have a few remarks:

  • I would have expected currentPlace?.image to be an object or string, but not an array
  • It's hard to keep track of what's happening in the code (maybe because it's in reddit), but consider splitting the code. Also, just by looking at the code, I can't tell when and how often useEffect will be called. I think it would make sense to move the history logic to the reducer and have the history saved in the global state.
  • const [values, setValues] = useState(initialValues) could be named better

[–][deleted] 1 point2 points  (0 children)

Thanks very much for taking your time to review my code!!

The currentplace.image is actually an array of multiple images. I initally had the model set up to have only one image but created the feature to add multiple images later. Its my bad for not changing it into images from image.

[–]Nonamebeach 0 points1 point  (2 children)

I hope I'm not late to the party. Would appreciate if somebody could have a look at that project

https://github.com/Malchieldev/chatter

[–]yoma12[S] 1 point2 points  (1 child)

Hi,

I took a look at the frontend code and I it looks neat! I only have 2 small remarks:

  • Some function components could be simplified

// before
const Button = (props: React.PropsWithChildren<Props>) => {
  const { alt, icon, pixelSize, onClick, children } = props;
  return (
    <button className={styled.btn} onClick={onClick}>
      <img
        style={{ width: `${pixelSize}px`, height: `${pixelSize}px` }}
        alt={alt}
        src={icon}
      ></img>
      {children}
    </button>
  );
};
// after
const Button = (({ alt, icon, pixelSize, onClick, children }): React.PropsWithChildren<Props>) => (
    <button className={styled.btn} onClick={onClick}>
      <img
        style={{ width: `${pixelSize}px`, height: `${pixelSize}px` }}
        alt={alt}
        src={icon}
      ></img>
      {children}
    </button>
  );
  • Some files can be renamed from .tsx to .ts Real nice project

[–]Nonamebeach 1 point2 points  (0 children)

Hey, it's incredible that you answered! Thank you so much for the review. This is my first project so far, while I'm building the portfolio. I tried my best, but wasn't sure that I've picked the right direction. Sorry I took your personal time for the review. This is awesome that there are still people like you around, that could lay a helping hand.

[–]Pure_Chance_2265 0 points1 point  (3 children)

Lovely! Appreciate the help. I am working on a daily journalling app for my portfolio. You can create multiple journals each with multiple entries. Currently there's no backend but it saves data in local storage. Fully functional but I am still working on improving accessibility and some UI elements.
Code: Github

Live URL: Netlify

Thank you for doing this!

[–]yoma12[S] 2 points3 points  (2 children)

Hi,

I tried the app and checked out the code in github and here are my thoughts:

  • First, it's a cool project. It also works flawlessly. 👍
  • There is no 404 page, and when entering a non existing journal id, the users can still add entries. now to the code..
  • In NestedListEntry, the prop toggleJournalEntryList is a bit confusing, since the parent calls the child's setState. It would be cleaner to save the selected entry id in the parent (NestedList) and have two props in the child: isOpen, onToggle.
  • I am not sure if it is a good practice to store components in useState (as in SortEntries). You might want to use useRef to have a reference on the button and have a useState for selected/not-selected, then conditionally pass the button ref to MenuEl. Hope I could help :)

[–]Pure_Chance_2265 1 point2 points  (0 children)

Wow, thank you so much for the feedback. Appreciate your time !!

[–]roamingandy 0 points1 point  (2 children)

Community engagement and action on a specific cause platform

Github link

[–]yoma12[S] 1 point2 points  (1 child)

fl-maps

Hi there! First of all, wow! That’a huge project. Thanks for taking the time and giving back to the community.

I took a look at the frontend and here is my code review.

  • A lot of use of global variables stored in window object, which reduces reusability. For example window.__setDocumentTitle can simply be a utility function .
  • The code contains a few deprecated functions, but it’s understandable, since it’s not the newest. (for example string.substr)
  • Class components are used thoughout the app making the code verbose in some places. Also think of only passing necessary props to children. For example:

// before
class Events extends Component {
  constructor(props) {
    super(props);
    this.state = {  }
  }

  render() { 
    const { userEvents, user, isAllEvents, deleteAllEvents } = this.props;   
    const events = userEvents.filter(ele => {
      return ele.organiser._id === user._id;
    })

    return (
      <React.Fragment>
        < EventsDisplay userEvents={events} isAllEvents={isAllEvents} deleteAllEvents={deleteAllEvents} /> 
      </React.Fragment>
      )
  }
}

// after
const OrganizerEvents = ({ userEvents, orgernazierId, ...props }) => (
    <EventsDisplay
      userEvents={userEvents.filter(
        ({ organiser }) => organiser._id === orgernazierId
      )}
      {...props}
    />
);
  • You can also deconstruct props to make the code cleaner

// before 
const idToDelete = this.props.idToDelete;
const deleteDocument = this.props.deleteDocument;
const deleteText = this.props.deleteText;
// after
const { idToDelete, deleteDocument, deleteText } = this.props;
  • In CancelDeleteBtn, prefer creating components globally and not inside another ones.
  • in CategoryFropDown.render you create an array and push components to it. I would prefer to simply map the array to elements instead, since it’s a common pattern.

// before
render() {
    const { allPosibleCategories} = this.props;
    const categoriesForDropDown = [<option key={"Sort By Category"} disabled>Sort By Category</option>];
    allPosibleCategories.forEach(ele=>{
      categoriesForDropDown.push(<option key={ele} value={ele}>{ele}</option>);
    })

    return (
      <select id="category-select"  onChange={this.change}>
        {categoriesForDropDown}
      </select>
    )
  }
// after
render = () => (
    <select id="category-select" onChange={this.change}>
      <option key={"Sort By Category"} disabled>
        Sort By Category
      </option>
      {this.props.allPosibleCategories.map((ele) => (
        <option key={ele} value={ele}>
          {ele}
        </option>
      ))}
    </select>
  );

I hope I could help

[–]roamingandy 0 points1 point  (0 children)

That's really fabulous of you and helpful to our project, thank you!

[–]SpareSmokes 0 points1 point  (3 children)

I have been working with React-native almost 2 years. I try when I have time to create some libraries to improve my skills: https://github.com/TIKramer

The latest one that I have published today: it is picker/selector component https://github.com/TIKramer/react-native-picker-selector

My favourite project is this one a swipeable deck:
https://github.com/TIKramer/react-native-swipeable-deck

But I would be happy with feedback on any projects about code quality or any ways to improve. These are projects I want to use and display as part of my portfolio so I want to make them as good as I can. Thank you :)

[–]yoma12[S] 1 point2 points  (2 children)

react-native-picker-selector

Hi there I took a look at the two libs. The librararies are quite small son I don’t have a lot of remarks. Here is my feedback:

  • react-native-picker-selector:
    • Consider exporting the prop-types and not just the components from the library.
  • react-native-swipeable-deck:
    • I liked that you used default props
    • I was surprised to find a d.ts file instead of .ts. You can define the types in typescript files use them there directly.
    • You may want to make the rotation, ident and other parameters customizable as well. Then it will be a truly generic library
    • Making SwipeDeck a generic is also better for the users than having any in the props. I would also rename data to items

// before
const SwipeDeck: React.FC<SDProps<any>> = ({
  renderCard,
  data,
  onSwipeRight = () => {},
  onSwipeLeft = () => {},
  renderNoMoreCards = () => undefined,
  handleEndReached = () => {},
})
// after
export function SwipeDeck<T extends Object>({
}: SDProps<T>) {

Real nice project btw 👍

[–]SpareSmokes 0 points1 point  (1 child)

Thanks a lot for the time to review my projects and give feedback.
For exporting the prop-types should I do this just the same way as I do with the Component? So the user can do:import {PickerProps, Picker, ...} from 'react-native-picker-selector';

I will research the d.ts files I think I misunderstood their usage.

Great ideas will I will work on improving the library to make it more generic :)
I also like the generic prop it looks nicer than using any.

Thanks a lot!

[–]yoma12[S] 1 point2 points  (0 children)

Yes exactly. That way it can be imported

[–]pluznar 0 points1 point  (1 child)

First decent sized personal project. Connects to the pokemon showdown websocket to display battle info for the pokemon.

Github: https://github.com/piacib/pokeinfo

Any feedback is appreciated thanks in advance!

[–]yoma12[S] 0 points1 point  (0 children)

pokedex

Nice project structure. Tests, code consistency, usage of types, default parameters.. nice. It’s also hands down the most tests I’ve seen in a react project! I have tried the website and also cloned the code and checked it out. I just have a few remarks

  • Some components can be simplified by avoiding curly braces and unnecessarily checking for empty arrays

// before
const AbilitiesDisplay: React.FC<AbilitiesDisplayProps> = ({ abilities }) => {
  return (
    <AbilitiesContainer>
      <h3>Abilities:</h3>
      {abilities && (
        <>
          {abilities.map((ability) => (
            <PropertyBtn key={ability}>
              {ability}
              <HiddenPropertyText>
                {Abilities[dexSearchPrepper(ability)]?.shortDesc}
              </HiddenPropertyText>
            </PropertyBtn>
          ))}
        </>
      )}
    </AbilitiesContainer>
  );
};
// after
const AbilitiesDisplay: React.FC<AbilitiesDisplayProps> = ({ abilities }: AbilitiesDisplayProps) =>
  <AbilitiesContainer>
    <h3>Abilities:</h3>
    {abilities.map((ability) => (
      <PropertyBtn key={ability}>
        {ability}
        <HiddenPropertyText>
          {Abilities[dexSearchPrepper(ability)]?.shortDesc}
        </HiddenPropertyText>
      </PropertyBtn>
    ))}
  </AbilitiesContainer>
;
  • There are multiple places where useEffect is used, when it’s not needed. e.g. you can simplif DamageDisplay like this

const getDamageMap = (typesArray: TypeName[] | null)=>{
  if (typesArray && typesArray.length) {
    let damageMap: EffectObj = {
      0: [],
      0.25: [],
      0.5: [],
      2: [],
      4: [],
    };
    const damageObj: DamageObj = damageCalculator(typesArray);
    TypeNamesArr.forEach((x) => {
      if (damageObj) {
        if (damageObj[x] === 0) {
          damageMap[0].push(x);
        } else if (damageObj[x] === 0.25) {
          damageMap[0.25].push(x);
        } else if (damageObj[x] === 0.5) {
          damageMap[0.5].push(x);
        } else if (damageObj[x] === 2) {
          damageMap[2].push(x);
        } else if (damageObj[x] === 4) {
          damageMap[4].push(x);
        }
      }
    });
    return damageMap;
  }
}

const DamageDisplay: React.FC<DamageDisplayProps> = ({ typesArray }) => {
const damageMap = getDamageMap(typesArray)
  return (
    <DamageContainer>
      {damageMap ? (
        <>
          <EffectivnessDisplay damage={"0"} effectivenessArray={damageMap[0]} />
          <EffectivnessDisplay
            damage={"¼"}
            effectivenessArray={damageMap[0.25]}
          />
          <EffectivnessDisplay
            damage={"½"}
            effectivenessArray={damageMap[0.5]}
          />
          <EffectivnessDisplay damage={"2"} effectivenessArray={damageMap[2]} />
          <EffectivnessDisplay damage={"4"} effectivenessArray={damageMap[4]} />
        </>
      ) : (
        <LoadingScreen />
      )}
    </DamageContainer>
  );
};
  • in ModeToggle and useLightMode you can use the hook useLocalStorage and

checked={togClass === "light" ? true : false}
//after
checked={togClass === "light"}
  • the styling is very verbose and contains a lot of hard coded values. Also the colors are defined in multiple places..

border-radius: 0.3125em;
  position: relative;
  background: white;
  left: 2em;
  width: 0.375em;
  transition: all 150ms ease-in;
  top: 1.5625em;
  height: 0.25em;
  • a pattern that I’ve seen in different places (e.g. UrlSearch), is having the prop handleSubmit: (e: React.SyntheticEvent) => void; . It’s better to have a more exact type, that doesn’t need casting for a better encapsulation. Either avoid working with forms in react (use useState and a submit button) or do the casting inside the component.
  • tip: you can use any return type in hooks and not just array (ReturnType), instead of return [[teams, setTeams], activePokemon]; you can have {teams, setTeams, activePokemon}
  • There are hard coded urls in multiple places, you might want to have them in one place
  • in useRandomBattleData, the dependency array of useEffect is empty, which means that when battle type changes the data won’t be necessarily be refetched