radix-ui / themes

Radix Themes is an open-source component library optimized for fast development, easy maintenance, and accessibility. Maintained by @workos.
https://radix-ui.com/themes
MIT License
5.18k stars 187 forks source link

[Slider] Issue - unreliable rendering of slider theme component and errors with primative - nextjs14 #186

Closed aaa3334 closed 8 months ago

aaa3334 commented 8 months ago

Using Nextjs14 and trying to load this inside a form. I am unsure if it is just me who is doing this wrong or if the component isnt fully updated with nexjs14... one of the errors is an HTML error (which is only thrown when I am using the slider primative) and the hydration errors also only occur when using the primative. Dynamically importing it breaks the functionality...

1) I could not get the plain component to render at all sometimes then other times it worked... so I am not sure why it was unreliably loading there. (Sometimes it looked more like a toggle switch). But either way I need the values from the toggle out on eg. a tooltip on the Slider so it seems like the plain Slider would not work even when I did manage to get it to work (maybe 50% of the time it loaded properly).

2) Then I used the primatives to achieve this and had the code: "use client";

import * as Slider2 from "@radix-ui/react-slider"; import React, { useReducer, useRef } from "react"; import "./styles.css"; import { Box, Flex, Grid, Text, Tooltip } from "@radix-ui/themes";

let value2 = [25, 50]; // Define value2

const SliderComp = () => { const valueRef = useRef([25, 50]); const [, forceUpdate] = useReducer((x) => x + 1, 0); return ( <>

Select length: { valueRef.current = value; forceUpdate(); }} name="sliderRange" >
</>

); };

export default SliderComp;

But this gives hydration errors and an HTML error: Warning: Expected server HTML to contain a matching

in . div PopperContent SlotClone Slot Primitive.div DismissableLayer.... [Error] Error: Hydration failed because the initial UI does not match what was rendered on the server. throwOnHydrationMismatch (react-dom.development.js:7076) tryToClaimNextHydratableInstance (react-dom.development.js:7121) updateHostComponent$1 (react-dom.development.js:16503) callCallback (react-dom.development.js:20461) dispatchEvent invokeGuardedCallbackImpl (react-dom.development.js:20510) invokeGuardedCallback (react-dom.development.js:20585) beginWork (react-dom.development.js:26763) performUnitOfWork (react-dom.development.js:25587) workLoopConcurrent (react-dom.development.js:25573) renderRootConcurrent (react-dom.development.js:25529) performConcurrentWorkOnRoot (react-dom.development.js:24382) workLoop (scheduler.development.js:261) flushWork (scheduler.development.js:230) performWorkUntilDeadline (scheduler.development.js:534) [Error] Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>. (anonymous function) (app-index.js:34) (anonymous function) (hydration-error-info.js:41) printWarning (react-dom.development.js:94) error (react-dom.development.js:68) errorHydratingContainer (react-dom.development.js:36087) recoverFromConcurrentError (react-dom.development.js:24471) performConcurrentWorkOnRoot (react-dom.development.js:24420) workLoop (scheduler.development.js:261) flushWork (scheduler.development.js:230) performWorkUntilDeadline (scheduler.development.js:534) [Error] Error: Hydration failed because the initial UI does not match what was rendered on the server. reportError onRecoverableError (on-recoverable-error.js:20) commitRootImpl (react-dom.development.js:26145) commitRoot (react-dom.development.js:25907) commitRootWhenReady (react-dom.development.js:24627) finishConcurrentRender (react-dom.development.js:24592) performConcurrentWorkOnRoot (react-dom.development.js:24437) workLoop (scheduler.development.js:261) flushWork (scheduler.development.js:230) performWorkUntilDeadline (scheduler.development.js:534) [Error] Error: Hydration failed because the initial UI does not match what was rendered on the server.

Warning: Expected server HTML to contain a matching

in .

See more info here: https://nextjs.org/docs/messages/react-hydration-error reportError onRecoverableError (on-recoverable-error.js:20) commitRootImpl (react-dom.development.js:26145) commitRoot (react-dom.development.js:25907) commitRootWhenReady (react-dom.development.js:24627) finishConcurrentRender (react-dom.development.js:24592) performConcurrentWorkOnRoot (react-dom.development.js:24437) workLoop (scheduler.development.js:261) flushWork (scheduler.development.js:230) performWorkUntilDeadline (scheduler.development.js:534) [Error] Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering. reportError onRecoverableError (on-recoverable-error.js:20) commitRootImpl (react-dom.development.js:26145) commitRoot (react-dom.development.js:25907) commitRootWhenReady (react-dom.development.js:24627) finishConcurrentRender (react-dom.development.js:24592) performConcurrentWorkOnRoot (react-dom.development.js:24437) workLoop (scheduler.development.js:261) flushWork (scheduler.development.js:230) performWorkUntilDeadline (scheduler.development.js:534) [Error] Failed to load resource: the server responded with a status of 400 (Bad Request) (__nextjs_original-stack-frame, line 0) [Error] Failed to load resource: the server responded with a status of 400 (Bad Request) (__nextjs_original-stack-frame, line 0)

3) Note I also tried a dynamic import but this broke the tooltip functionality and also half the time one of the SliderThumbs did not show up... (error for this one: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of SlotClone. LoadableComponent SlotClone.....)

Code for this: "use client";

//import * as Slider2 from "@radix-ui/react-slider"; import React, { useReducer, useRef } from "react"; import "./styles.css"; import { Box, Flex, Grid, Text, Tooltip } from "@radix-ui/themes"; import dynamic from "next/dynamic";

const SliderRoot = dynamic( () => import("./SliderWrapper").then((mod) => mod.SliderRoot), { ssr: false } ); const SliderTrack = dynamic( () => import("./SliderWrapper").then((mod) => mod.SliderTrack), { ssr: false } ); const SliderRange = dynamic( () => import("./SliderWrapper").then((mod) => mod.SliderRange), { ssr: false } ); const SliderThumb = dynamic( () => import("./SliderWrapper").then((mod) => mod.SliderThumb), { ssr: false } );

let value2 = [25, 50]; // Define value2

const SliderComp = () => { const valueRef = useRef([25, 50]);

const [, forceUpdate] = useReducer((x) => x + 1, 0); return ( <>

Select length range: { valueRef.current = value; forceUpdate(); }} name="sliderRange" >
</>

); };

export default SliderComp;

Note styles.css I had to edit to get it to look similar to what the example was - the default i copied and pasted had the range being white and the outside of the slider being coloured which did not match the examples on the 'Slider' componenents.

@import '@radix-ui/colors/black-alpha.css'; @import '@radix-ui/colors/violet.css'; @import '@radix-ui/colors/iris.css';

.SliderRoot { position: relative; display: flex; align-items: center; user-select: none; touch-action: none; width: 200px; height: 20px; }

.SliderTrack {

background-color: white; position: relative; flex-grow: 1; border-radius: 9999px; height: 4px; box-shadow: 0 0 0 1px var(--iris-a4); }

.SliderRange {

background-color: var(--iris-a10); position: absolute; border-radius: 9999px; height: 100%; }

.SliderThumb { display: block; width: 15px; height: 15px; background-color: white; box-shadow: 0 1px 2px var(--black-a7); border-radius: 10px; } .SliderThumb:hover { background-color: var(--violet-3); } .SliderThumb:focus { outline: none; box-shadow: 0 0 0 2px var(--black-a8); }

vladmoroz commented 8 months ago

It would be hard to provide a quality answer for all the different questions here. It’s a bit hard to understand what’s going on.

Please isolate your problems and create separate issues with minimal reproductions.