简体   繁体   中英

Why does renderToString throws error about useLayoutEffect while rendering Material-UI component?

I am using React v.16.12.0 and @MaterialUI/core v4.8.1.

I am trying to create custom icon for React Leaflet Marker. The icon is a Fab component from Material-UI. To do that, I need to pass a HTML string to L.DivIcon (DivIcon Docs) Leaflet component, so I am using renderToString() method from react-dom/server .

And it is throwing an error:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. in NoSsr in button in ForwardRef(ButtonBase) in WithStyles(ForwardRef(ButtonBase)) in ForwardRef(Fab) in WithStyles(ForwardRef(Fab)) (at src/index.js:9)

While I'm not using useLayoutEffect.

Here's a simple example:

import React from "react";
import ReactDOM from "react-dom";
import ReactDOMServer from 'react-dom/server';
import Fab from '@material-ui/core/Fab';

function App() {
  return ReactDOMServer.renderToString(
    <Fab size="small" variant="extended">
      Test
    </Fab>);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Online: https://codesandbox.io/s/material-ui-rendertostring-tc90b

Why is it throwing that error? What's incorrect with this code? Is there any other way to generate HTML-String from Material-UI Component in order to pass it as an icon to Leaflet Marker?

I used renderToStaticMarkup to render a custom marker. Marker is getting rendered but still getting the warnings.

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { renderToStaticMarkup } from "react-dom/server";
import { divIcon } from "leaflet";
import { Map, TileLayer, Marker, Popup } from "react-leaflet";
import Fab from "@material-ui/core/Fab";

import "./styles.css";

class App extends Component {
  state = {
    lat: 51.505,
    lng: -0.091,
    zoom: 13
  };

  render() {
    const position = [this.state.lat, this.state.lng];
    const iconMarkup = renderToStaticMarkup(
      <Fab size="small" variant="extended">
        Test
      </Fab>
    );
    const customMarkerIcon = divIcon({
      html: iconMarkup
    });

    return (
      <div>
        <Map center={position} zoom={this.state.zoom}>
          <TileLayer
            attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
          />
          <Marker position={position} icon={customMarkerIcon}>
            <Popup>
              A pretty CSS3 popup. <br /> Easily customizable.
            </Popup>
          </Marker>
        </Map>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Working code: https://codesandbox.io/s/react-leaflet-icon-material-mx1iu

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM