Chris Eckert

Chris Eckert

I am a software engineer focused on frontend development whose main goal is the ensure type-safety, code quality and knowledge sharing.

+300K

MAUs impacted

continuesly developed features and improvements, seamlessly delivered to a large audience

Last updated Apr. 23

+1M

users impacted from freelance, personal and work projects

Interested in a chat?

I am always open to help you, your business and in general talk about the tech industry.

Send me a message
ReactNext.jsTypeScriptTailwindCSSCVARadix UIZodPrismatRPCTanstack QueryGraphQLVercelClerk.devPlanetscaleUpstashStorybook.jsApolloReact NativeTesting LibraryJestPlaywrightSanityT3

* My prefered stack for projects, see my cv or uses page for a detailed list.

Latest articles

How to Mock Functions Per Test in TypeScript And Jest

How to Mock Functions Per Test in TypeScript And Jest

Have you ever had the need for updating the UI based on an underlying hook or function in a unit test? Then this tidbit might be just right for you. I recently came across this issue, the solution was quite simple, just make a mock implementation of the underlying function and change the received values - right? ![](/assets/images/jest-mock-meme.jpeg) Yes and no - the solution works but Typescript isn't too happy. The reason is that Typescript does not automatically assign the mocked capabilities to the original function after using `jest.mock` to overwrite the implementation. There is no automatic inheritance. ```TypeScript import { useFeatureFlags } from 'hooks/useFeatureFlags' jest.mock('hooks/useFeatureFlags') // ERROR: Property 'mockImplementation' does not exist on type [useFeatureFlag] useFeatureFlags.mockImplementation(() => ({ MY_FEATURE_FLAG: true })) ``` Sadly, this is one of the instances where Jest and TypeScript aren't the best of friends and we will have to cast the desired implementation ourselves. Luckily, Jest comes with the type of `MockedFunction` as a generic. We can then easily slot in our original function type with the typeof interpreter. We will have to store the mocked function on its own variable to get the best effect, this will also show the correct intent for the next person viewing the code. ```TypeScript import { useFeatureFlags } from 'hooks/useFeatureFlags' jest.mock('hooks/useFeatureFlags') const useFeatureFlagsMock = useFeatureFlags as jest.MockedFunction<typeof useFeatureFlags> ``` We can now use the jest capabilities to mock the outcome of the function. ```TypeScript useFeatureFlagsMock.mockImplementation(() => ({ MY_FEATURE_FLAG: true })) ``` It is now possible to get different UI states based on the mocked functions return value, within single test cases or within different scopes. Here is a contrived example with all of the above together. ```TypeScript import { useFeatureFlags } from 'hooks/useFeatureFlags' jest.mock('hooks/useFeatureFlags') const useFeatureFlagsMock = useFeatureFlags as jest.MockedFunction<typeof useFeatureFlags> describe('feature flag test', () => { it('should show if feature flag is on', async () => { useFeatureFlagsMock.mockImplementation(() => ({ MY_FEATURE_FLAG: true })) ... }) it('should not show if feature flag is on', async () => { useFeatureFlagsMock.mockImplementation(() => ({ MY_FEATURE_FLAG: true })) ... }) }) ``` You can of course throw this into a beforeEach method or do whatever else you usually would do with Jest to achieve your test completion.

Apr 16, 2023
How to Create a Theme Switcher in React

How to Create a Theme Switcher in React

Theme switchers have become more and more of a standard during the last few years. Mostly used as a night mode toggle. There are a wide variety of approaches for creating your desired effect, but some seem overly complex to get up and running for such a small task. With React we get some tools that makes the addition of a theme switcher very easy to implement and also manage with the componentization of our code. > This project can easily be followed with the basic create-react-app setup. > > The final code can be found here - https://codesandbox.io/s/blog-theme-switcher-j0o2g Lets start of by building a very simple switch component. I created a components folder in my project directory and nested a folder for our ThemeSwitcher component. At first we create our component. This is just a very basic functional component. I downloaded two SVG icons from [FontAwesome](https://fontawesome.com/). We will later switch between these based on our theme state. ```js import React from "react"; import { ReactComponent as Sun } from "../../icons/sun.svg"; import { ReactComponent as Moon } from "../../icons/moon.svg"; const ThemeSwitcher = () => { return ( <div className="switcher"> <Sun /> <Moon /> </div> ); }; export default ThemeSwitcher; ``` We add a little bit of CSS to handle the sizing and that's it. ```css .switcher { width: 50px; cursor: pointer; } @media (min-width: 420px) { .switcher { width: 1.5rem; } } ``` And lastly create a index.js file which main focus is to easily let us export our component. It also lets us import our CSS in a efficient way. ```js import "./ThemeSwitcher.css"; export { default } from "./ThemeSwitcher"; ``` You can now import the Switcher component to the page where you want to display it or keep it in a wrapper if it needs to be shown on every page. I created a few other elements, which we will use to show how the theme changes. ![](/assets/images/switch-initial-setup.png) Right now our switcher doesn't do much and for one thing it doesn't even switch between the icons - lets fix that. ### Adding a global state For having an updatable state we will use the `React context api`. With context we are able to create global state which is available everywhere in our app. This of course entails that we use functional components. We could use class based components and a normal state, but that would mean we would have to prop our values, functions etc. down the component tree. This could lead to harder debugging and lessen our flexibility with the components. Setting up the context api is dreaded by some, you have to keep track of providers and consumers. It can become a bit messy. Below I would like to introduce an approach for setting up a context without a big fuss. Lets create a context folder in the project source folder and add our `themeContext.js` file. Here we first setup our base context without any default context state. Which of course would return us undefined when using the context. ```js import React, { createContext } from "react"; import PropTypes from "prop-types"; export const ThemeContext = createContext(); ``` We could of course define our values inside the create context but we would lose a lot of functionality. Instead of using our context directly in our files and setting our state in that initial component, like a layout component or the like. But it is way nicer having all of our context logic in one place. So we create a `ThemeContextProvider` component below, in here we can setup states, global functions, variables etc. So we setup our initial theme state and provide it to the context, thereby making it available to the children through `useContext`. ```js import React, { createContext } from "react"; import PropTypes from "prop-types"; // initialize our theme context export const ThemeContext = createContext(); //setup a provider component, wrapped views, components etc. // can access the context through here export const ThemeContextProvider = ({ children }) => { const [theme, setTheme] = useState("light"); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); }; ThemeContextProvider.propTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node, ]).isRequired, }; ``` We export both the ThemeContext and the provider component from the file to access theme throughout the app. Now we will wrap our app component with our provider in the `index.js` file. If you have multiple routes or the like, you should make sure to wrap them, so that the state is available in all the routes. ```js // ... import { ThemeContextProvider } from "./context/themeContext"; const rootElement = document.getElementById("root"); ReactDOM.render( <React.StrictMode> {/* wrap the app component */} <ThemeContextProvider> <App /> </ThemeContextProvider> </React.StrictMode>, rootElement ); ``` We are now able to use our context in all our child components. So head over to our switcher component to destructure our theme value and update function. ### Setting up the logic We'll add it to our wrapper `div` but we need to add some logic, so we'll configure an update function. This one will check whether or not the theme state is equal to "light", based on this we will either set the theme to "dark" or "light". We'll also show either the sun icon or the moon icon based on our state ```js import React, { useContext } from "react"; // ... import { ThemeContext } from "../../context/themeContext"; const ThemeSwitcher = () => { const { theme, setTheme } = useContext(ThemeContext); const isLight = theme === "light"; const updateTheme = () => (isLight ? setTheme("dark") : setTheme("light")); return ( <div className="switcher" onClick={() => updateTheme()}> {!isLight && <Sun />} {isLight && <Moon />} </div> ); }; export default ThemeSwitcher; ``` You can now switch between the two icons by updating our global context state. To control the other elements of the page we will add our theme value to our outermost parent component. In our case the `App.js` file. ### Adding styling to your app You can either add the theme as a class property as we have provided it as string. We could also set it as a data-attribute, but I will go with the more traditional approach for now. ```js // ... import { ThemeContext } from "./context/themeContext"; export default function App() { const { theme } = useContext(ThemeContext); return <div className={`App ${theme}`}>{/* ... */}</div>; } ``` The next step is to setup our CSS and change styling when the `.dark` class is added to our base component. ```css .App { /* ... */ background: #fff; color: #202020; transition: all 0.2s ease-in-out; } .App.dark { background: #202020; color: #fff; } .button { /* ... */ background: #f2f2f2; color: #5f5f5f; transition: all 0.2s ease-in-out; } .dark .button { color: #f2f2f2; background: #6c737e; } .button:hover { filter: invert(10%); } .dark .button:hover { filter: invert(65%); } ``` You should now be able to easily switch your theme based on the added class. ![](/assets/images/switch-side-by-side.png) Great job but we can definitely improve our approach for changing the colors. Adding a `.dark` property to all possible classes that need to change can become quit cumbersome, especially in larger applications. What if colors need to change suddenly, you would have to go through your whole app and adjust your colors one by one. ### Optimizing with CSS Variables Luckily CSS has given us variables, a very powerful way to have global CSS variables that can change on runtime, something that is not supported in the very popular Sass library. First of lets define our variables at the top of the page. Ideally, in larger projects, you would ensure that these would be defined in your outermost CSS file to ensure that they are available throughout your whole application. Remember the file with your variables should be loaded in on every page. ```css :root { --primary: #202020; --secondary: #f2f2f2; --background: #ffffff; } ``` Now can change the variables when the `.dark` class has been added. Doing this will overwrite our variables when the `.dark` class is added to our parent element. This saves us from writing a lot of the same styling with minor changes. ```css .dark { --primary: #f2f2f2; --secondary: #2b2b2b; --background: #202020; } ``` The last thing we have to do is switch out our hardcoded colors with our variables. We do that by adding `var()` and add the variable name within the parentheses. ```css .App { /* ... */ background: var(--background); color: var(--primary); /* ... */ } .button { /* ... */ background: var(--secondary); color: var(--primary); /* ... */ } ``` Now we can quickly change our variables to anything we want and the app will respond. <iframe src="https://codesandbox.io/embed/blog-theme-switcher-j0o2g?fontsize=14&hidenavigation=1&theme=dark&view=preview" style={{ width: "100%", height: "500px", border: 0, borderRadius: "4px", overflow: "hidden", }} title="blog-theme-switcher" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" ></iframe> Now if you are coding along you might notice that, with the approach above, we need to re-set our preferred theme each time we visit the page. If your page is a one-time drop-in that might be a-okay, but if you have regular users, they might grow tired of switching to their desired theme each time they visit your site. ### Configuring for persisting theme through local-storage So we need to somehow persist a users theme preference. Well you could setup user login and have it all stored in a database, but again that's a huge feat for just storing whether or not you like night mode. Instead we can take advantage of the users browser, where we have access to `local-storage`. First up we can add a `storeTheme` function that handles both setting the theme to our global state as well as storing in the local storage. This will save us from writing the same logic twice, as we are doing the same thing on each side of the ternary operator. Now instead of setting the global variable directly in the `updateTheme` function we can just pass in the string we want to store in both our `state` and `local-storage`. Lastly we need to add a `useEffect` for checking if there is a theme value stored in our `local-storage`. If that is the case then we want to update our theme context with the stored value. We set an empty array as our dependency for the `useEffect`, to say, we only want this to run on its initial mount. And that's it! ```js // 3 useEffect(() => { const persistantTheme = window.localStorage.getItem("theme"); if (persistantTheme) { setTheme(persistantTheme); } }, []); // 1 const storeTheme = (themeValue) => { setTheme(themeValue); window.localStorage.setItem("theme", themeValue); }; //2 const updateTheme = () => (isLight ? storeTheme("dark") : storeTheme("light")); ``` > You will see small flash on initial load as the color switches, something that could be fixed in different ways for example with SSR but that's for another post. If you are looking for some additional or supplementary reading on the topics covered in this tutorial, please take a look at the following links. - [Kent C. Dodds - Context Tutorial](https://kentcdodds.com/blog/how-to-use-react-context-effectively) - [MDN's Guide on CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) - [Official React Context Docs](https://reactjs.org/docs/context.html)

Apr 23, 2020
Read more articles

Latest projects

Browse more projects

Prismic

Senior Software Engineer

Sep 2023 - Present

TV 2 Danmark

Software Engineer

May 2022 - Aug 2023

TV 2 Danmark

Frontend Consultant

Mar. 2020 - May 2022

Abtion Logo

Abtion

Software Engineer

Feb. 2019 - May 2022

Freelance

Software Engineer

Apr. 2018 - present

Morningscore Logo

Morningscore

React Developer

Oct. 2018 - Nov. 2018

Morningtrain Logo

Morningtrain

React Intern

Aug. 2018 - Dec. 2018

Download CV