Computations created outside a `createRoot` or `render` will never be disposed

I am migrating my React application to Solid and I am encountering some problems. When using this component that provides me with information about a phone's DDI, I get the error in image 1 and the component is this one:
const flag = (name) => `https://url-for-search-img/${name}.jpg`

export const countryList = [
    {
        flag: <img style={{width: '18px'}}  src={flag('br')}/>,
        countryLabel: 'Brazil | Brasil',
        countryCode: 'br',
        value: '55',
        code: '+55'
    },

    {
        flag: <img style={{width: '18px'}}  src={flag('mx')} />,
        countryLabel: 'Mexico | México',
        countryCode: 'mx',
        value: '52',
        code: '+52'
    }
]
const flag = (name) => `https://url-for-search-img/${name}.jpg`

export const countryList = [
    {
        flag: <img style={{width: '18px'}}  src={flag('br')}/>,
        countryLabel: 'Brazil | Brasil',
        countryCode: 'br',
        value: '55',
        code: '+55'
    },

    {
        flag: <img style={{width: '18px'}}  src={flag('mx')} />,
        countryLabel: 'Mexico | México',
        countryCode: 'mx',
        value: '52',
        code: '+52'
    }
]
And I am using this component here:
{countryList.map((countryItem, countryItemIndex) => (
            <option
              value={`${countryItem.value}`}
              key={'flag_option_v1_' + countryItemIndex}
            >
              {countryItem.code}
            </option>
          ))}
{countryList.map((countryItem, countryItemIndex) => (
            <option
              value={`${countryItem.value}`}
              key={'flag_option_v1_' + countryItemIndex}
            >
              {countryItem.code}
            </option>
          ))}
I tried changing the array to a function, like this:
countryList = [...]
countryList.map
countryList = [...]
countryList.map
countryList = () => [...]
countryList().map
countryList = () => [...]
countryList().map
But I still get errors, as shown in image 2.
No description
No description
5 Replies
Alex Lohr
Alex Lohr2mo ago
Use <For each={countryList}>{(county, index) => ...}</For>
peerreynders
peerreynders2mo ago
Here you are trying to create
const flag = (name) => `https://url-for-search-img/${name}.jpg`

export const countryList = [
    {
        flag: <img style={{width: '18px'}}  src={flag('br')}/>,
        countryLabel: 'Brazil | Brasil',
        countryCode: 'br',
        value: '55',
        code: '+55'
    },
// ...
]
const flag = (name) => `https://url-for-search-img/${name}.jpg`

export const countryList = [
    {
        flag: <img style={{width: '18px'}}  src={flag('br')}/>,
        countryLabel: 'Brazil | Brasil',
        countryCode: 'br',
        value: '55',
        code: '+55'
    },
// ...
]
components during module load time. That is a no-go in Solid because JSX creates its own "effect bubble" which has to be created under a reactive root which isn't created until here
render(() => <App />, document.getElementById("app")!);
render(() => <App />, document.getElementById("app")!);
for the components running under it. So countryList should be purely data and a component for the <img> should be factored out and only used inside another component running under render when actually needed with an item from countryList. Also Solid doesn't use the key prop.
<For each={countryList}>
{(item, _index) => <option value={`${item.value}`}>{item.code} </option>}
</For>
<For each={countryList}>
{(item, _index) => <option value={`${item.value}`}>{item.code} </option>}
</For>
With For Solid would use the item object reference to key the created <option> element. This is why it is important to keep object references stable which means you are going to be using createStore and reconcile for data coming from the server a lot sooner than you may think.
Gabriel Viol
Gabriel Viol2mo ago
I understand that I'm already using createStore here. Would it be best to add this country list to the store, even though it's a static list? And could this be why I'm getting this error? "Error: Hydration Mismatch. Unable to find DOM nodes for hydration key: 0-2-0-0-2-0-0-0-1-0-0-1-0-0-0-0"
peerreynders
peerreynders2mo ago
even though it's a static list?
No, I was talking about data coming from the server where different objects in memory may represent the same entity. The primary issue is:
      flag: <img style={{width: '18px'}}  src={flag('br')}/>,
      flag: <img style={{width: '18px'}}  src={flag('br')}/>,
that has got to go. Secondarily replace the map in JSX with a For. The hydration error could be an issue that isn't related to any of the code that you have shown so far. Hydration errors tend to happen when something monkeys around with the DOM that Solid can't account for, in many cases it's UI libraries that modify the DOM independently, sometimes even the browser. A typical starting point is to look at View Source (drop the contents into a Prettier window for ease of inspection) and see whether the hydration key exists in the SSR source. If it does it's time to chase down what JavaScript is altering that part of the DOM during page load. Sometimes if it you send HTML that isn't "well formed" the browser will helpfully correct it leading to a hydration errors. So taking note of the differences between "view source" and the developer tools "Elements" view may provide a hint who is rearranging the DOM.
cirilla
cirilla2mo ago
Instead of flag being a JSX expression, you can make it a function that returns that e.g. () => <img ... and then change where you have flag to flag() so that the elements are not created eagerly