Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Troubleshooting "Module not found" error with react-dom/server in a Slack thread.

44 replies
Last updated: Jun 8, 2020
How do i solve:
Module not found: Error: Can't resolve 'react-dom/server'
• i have react-dom installed in package.json
Seems it tries to find it in:

studio/schemas/objects
Jun 8, 2020, 9:35 AM
How are you importing it at the moment?
Jun 8, 2020, 10:38 AM
import ReactDOMServer from "react-dom/server";
Jun 8, 2020, 10:39 AM
As stated here:
Jun 8, 2020, 10:39 AM
And it’s in your
package.json
under
dependencies
or
devDependencies
for example?
Jun 8, 2020, 10:42 AM
"react-dom": "^16.13.1",
under dependencies
Jun 8, 2020, 10:43 AM
Could you try removing your
node_modules
folder and
package-lock.json
file before running
npm install
to see if that resolves it?
Also, what Node version are you using (
node -v
)?
Jun 8, 2020, 10:50 AM
v12.16.3
Jun 8, 2020, 10:51 AM
It works on my website using React, so it must be something specific to Sanity
Jun 8, 2020, 10:56 AM
Updated to latest node version, no change
Jun 8, 2020, 10:59 AM
Here is the entire error if that helps:
Jun 8, 2020, 11:00 AM
Have you tried the above procedure as well with your
node_modules
folder and the
package-lock.json
file?
Jun 8, 2020, 11:00 AM
yes
Jun 8, 2020, 11:01 AM
Tried using both Npm and Yarn
Jun 8, 2020, 11:01 AM
Alright, thanks for confirming and testing with Yarn as well. I’ll try to reproduce and see if we have a workaround 🙂
Jun 8, 2020, 11:01 AM
Thank you (Removed Name) 🙂
Jun 8, 2020, 11:08 AM
Do you want me to send you the code?
Jun 8, 2020, 11:09 AM
No need, thanks - was able to reproduce. We’re looking it 🙂
Jun 8, 2020, 11:33 AM
Awesome 🙂
Jun 8, 2020, 11:33 AM
Thanks for the quick responses
Jun 8, 2020, 11:33 AM
Could you say a bit more about your use case for ReactDOMServer? Maybe there’s a workaround while this is not yet resolved?
Jun 8, 2020, 11:42 AM
I’m currently exporting icon names using icon-picker in Sanity, but this means i have to load all SVG icons on my website, which causes bloat.
Therefore i want it to just send the SVG code of the react-icon instead of just the name
Jun 8, 2020, 11:43 AM
this:
Jun 8, 2020, 11:44 AM
We’ll work on resolving the issue, but to have a workaround for now, I just managed to get this to function with a relative path instead:
import ReactDOMServer from '../node_modules/react-dom/server'
[You’d have to adapt this a bit depending on where you’re importing from]
Jun 8, 2020, 12:07 PM
Thank you, i will try that 🙂
Jun 8, 2020, 12:21 PM
I’m trying to do this:
{iconsArray.icons.map((icon) => {
    const Icon = ReactIcons[icon];
    const rendered = ReactDOMServer.renderToString(Icon());

    return (
        <>
            <span className="btn" onClick={() => clearSearch()}>
                <button
                    style={{
                        background: "transparent",
                        borderRadius: "0.1rem",
                        margin: "0.1rem",
                    }}
                    onClick={() =>
                        onChange(createPatchFrom(rendered))
                    }
                >
                    <Icon />
                </button>
            </span>
        </>
    );
})}
And loading like this in schema:

{
    title: "Velg et hovedikon",
    description: "Søk etter ikoner:",
    name: "icon",
    type: "string",
    inputComponent: IconPicker,
},
But getting this error:
Jun 8, 2020, 12:36 PM
I get it to render the SVG code as a string in Sanity, but i cannot manage to get it to set it as a value:
Jun 8, 2020, 12:48 PM
What does your
createPatchFrom
look like for the custom input component?
Jun 8, 2020, 12:51 PM
(or the entire
IconPicker
component)
Jun 8, 2020, 12:51 PM
// The patch function that sets data on the document
const createPatchFrom = (value) =>
    PatchEvent.from(value === "" ? unset() : set(String(value)));
Jun 8, 2020, 12:52 PM
Entire code looks like this:
Jun 8, 2020, 1:03 PM
import React from "react";
import ReactDOMServer from "../../node_modules/react-dom/server";
import PatchEvent, { set, unset } from "part:@sanity/form-builder/patch-event";
import FormField from "part:@sanity/components/formfields/default";

import * as ai from "react-icons/ai";
import * as bs from "react-icons/bs";
import * as di from "react-icons/di";
import * as fa from "react-icons/fa";
import * as fc from "react-icons/fc";
import * as fi from "react-icons/fi";
import * as gi from "react-icons/gi";
import * as go from "react-icons/go";
import * as gr from "react-icons/gr";
import * as io from "react-icons/io";
import * as md from "react-icons/md";
import * as ri from "react-icons/ri";
import * as ti from "react-icons/ti";
import * as wi from "react-icons/wi";
const ReactIcons = {
    ...ai,
    ...bs,
    ...di,
    ...fa,
    ...fc,
    ...fi,
    ...gi,
    ...go,
    ...gr,
    ...io,
    ...md,
    ...ri,
    ...ti,
    ...wi,
};

// The patch function that sets data on the document
const createPatchFrom = (value) =>
    PatchEvent.from(value === "" ? unset() : set(String(value)));

const IconPicker = (props) => {
    const { type, value = undefined, onChange } = props;
    const [iconsArray, setIconsArray] = React.useState({ icons: [] });
    const [pickerValue, setPickerValue] = React.useState([]);
    const [searchQuery, setSearchQuery] = React.useState();

    const handleChange = (query) => {
        setPickerValue(query);
        const arr = [];
        Object.keys(ReactIcons).map((go) => {
            if (
                go.toLowerCase().includes(query.toLowerCase()) &&
                query.length > 2
            ) {
                arr.push(go);
                setIconsArray({ icons: arr });
            }
        });
    };

    // If deleting searchquery, clear icons
    React.useEffect(() => {
        if (pickerValue.length < 2) {
            setIconsArray({ icons: [] });
        }
    }, [pickerValue]);

    // On icon select
    const getIcon = (icon) => {
        const Icon = ReactIcons[icon];
        return (
            <>
                <Icon />
            </>
        );
    };

    const clearSearch = () => {
        setPickerValue([]);
        setSearchQuery("");
    };
    return (
        <>
            <FormField
                label={type.title}
                description={
                    value !== undefined ? "Valgt ikon: " : type.description
                }
            >
                {value !== undefined ? (
                    <div style={{ position: "relative" }}>
                        <p style={{ fontSize: "2rem" }}>
                            {getIcon(value)} <b>{value}</b>
                        </p>
                        <button
                            style={{
                                fontSize: "1.5rem",
                                position: "absolute",
                                top: 0,
                                right: 0,
                                background: "transparent",
                                color: "red",
                                border: 0,
                            }}
                            onClick={() => onChange(createPatchFrom(""))}
                        >
                            {getIcon("AiFillCloseCircle")}
                        </button>
                    </div>
                ) : (
                    ""
                )}
                <input
                    type="text"
                    onChange={(event) => handleChange(event.target.value)}
                    className="DefaultTextInput_input_2wVzD text-input_textInput_31n9_ text-input_root_1xAqy"
                />
                {iconsArray.icons.map((icon) => {
                    const Icon = ReactIcons[icon];
                    const iconRendered = ReactDOMServer.renderToString(Icon());

                    return (
                        <>
                            <span className="btn" onClick={() => clearSearch()}>
                                <button
                                    style={{
                                        background: "transparent",
                                        borderRadius: "0.1rem",
                                        margin: "0.1rem",
                                    }}
                                    // Working:
                                    // onClick={() =>
                                    //     onChange(createPatchFrom(icon))
                                    // }
                                    // Not working
                                    onClick={() =>
                                        onChange(createPatchFrom(iconRendered))
                                    }
                                >
                                    <Icon />
                                </button>
                            </span>
                        </>
                    );
                })}
            </FormField>
        </>
    );
};

export default IconPicker;
Jun 8, 2020, 1:03 PM
Any idea what causes this?
Jun 8, 2020, 1:49 PM
createPatchFrom
expects a
String
value in this case, which it is likely not receiving from where
createPatchFrom
is called - with
icon
yes, but with
iconRendered
no.
This might be surprising, given that you use
renderToString()
to generate
iconRendered
. Could you try to console log the type of
iconRendered
to confirm it’s actually a string?
Jun 8, 2020, 2:09 PM
It says string
Jun 8, 2020, 2:11 PM
Do you think patchEvent gets the value before it is rendered to string somehow?
Jun 8, 2020, 2:25 PM
Would it be possible to use a promise or something?
Jun 8, 2020, 2:29 PM
What happens if you change the patch function to:
const createPatchFrom = value => PatchEvent.from(value === '' ? unset() : set(value))
Also, what value is logged here, simply
undefined
?
Jun 8, 2020, 2:46 PM
i will check
Jun 8, 2020, 2:48 PM
same error
Jun 8, 2020, 2:49 PM
And if you change
renderedIcon
to
icon
it still works with the original patch function?
In this earlier reply, if you change the icon to a different one, does it successfully update the SVG output directly?
https://sanity-io-land.slack.com/archives/C9Z7RC3V1/p1591620484416700?thread_ts=1591608917.403700&amp;cid=C9Z7RC3V1
Jun 8, 2020, 2:54 PM
I can output it as string and JSX underneath the search as you can see
Jun 8, 2020, 2:58 PM
Could you DM me a zip of your schema file for this plus the custom input component? Happy to have a look later today if I can spot anything 🙂
Jun 8, 2020, 3:00 PM
Of course 🙂 Incredible service
Jun 8, 2020, 3:01 PM
(Resolved in DM - rendering issue with
getIcon()
in the end, patch was perfect!) 🚀
Jun 8, 2020, 3:56 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?