-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Next.js runtime error #84
Comments
I combined all the answers from previous issues and I managed to get it working in Next.js with the following code: import "splitting/dist/splitting.css";
import "splitting/dist/splitting-cells.css";
const Component = () => {
let target;
setTimeout(() => {
if ( window && document && target ) {
const Splitting = require('Splitting');
Splitting({ by: "chars", target: target, });
}
});
return (
<>
<span ref={(el) => { target = el; }}>Lorem ipsum dolor sit amet</span>
</>
)
}
export default Component; |
if the ref is an arrow function, when exactly does it run? After component mounted ? |
Im having a similar issue cause I'm using it in a hook 'use client'
import 'splitting/dist/splitting.css'
import 'splitting/dist/splitting-cells.css'
import { useEffect, useRef } from 'react'
import Splitting from 'splitting'
import { randomNumber } from '~/lib/utils'
interface CellOptions {
position: number
previousCellPosition: number
}
class Line {
position = -1
cells: Cell[] = []
constructor(linePosition: number) {
this.position = linePosition
}
}
class Cell {
DOM: {
el: HTMLElement | null
} = {
el: null
}
position = -1
previousCellPosition = -1
original: string
state: string
color: string
originalColor: string
cache: any
constructor(DOM_el: HTMLElement, options: CellOptions) {
this.DOM.el = DOM_el
this.original = this.DOM.el.innerHTML
this.state = this.original
this.color = this.originalColor = getComputedStyle(
document.documentElement
).getPropertyValue('--color-text')
this.position = options.position
this.previousCellPosition = options.previousCellPosition
}
set(value: string) {
this.state = value
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.DOM.el!.innerHTML = this.state
}
}
class TypeShuffle {
DOM: {
el: HTMLElement | null
} = {
el: null
}
lines: Line[] = []
lettersAndSymbols: string[] = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'!',
'@',
'#',
'$',
'&',
'*',
'(',
')',
'-',
'_',
'+',
'=',
'/',
'[',
']',
'{',
'}',
';',
':',
'<',
'>',
',',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'
]
effects: Record<string, () => void> = {
fx: () => this.fx()
}
totalChars = 0
isAnimating = false
constructor(DOM_el: HTMLElement) {
this.DOM.el = DOM_el
const results = Splitting({ target: this.DOM.el, by: 'lines' })
results.forEach((s: any) => Splitting({ target: s.words }))
for (const [linePosition, lineArr] of results[0].lines.entries()) {
const line = new Line(linePosition)
const cells: Cell[] = []
let charCount = 0
for (const word of lineArr) {
for (const char of Array.from(
word.querySelectorAll('.char')
) as HTMLElement[]) {
cells.push(
new Cell(char, {
position: charCount,
previousCellPosition: charCount === 0 ? -1 : charCount - 1
})
)
++charCount
}
}
line.cells = cells
this.lines.push(line)
this.totalChars += charCount
}
}
clearCells() {
for (const line of this.lines) {
for (const cell of line.cells) {
cell.set(' ')
}
}
}
getRandomChar() {
return this.lettersAndSymbols[
Math.floor(Math.random() * this.lettersAndSymbols.length)
]
}
fx() {
const MAX_CELL_ITERATIONS = 10
let finished = 0
this.clearCells()
const loop = (line: Line, cell: Cell, iteration = 0) => {
if (iteration === MAX_CELL_ITERATIONS - 1) {
cell.set(cell.original)
++finished
if (finished === this.totalChars) {
this.isAnimating = false
}
} else {
const randomChar = this.getRandomChar()
if (randomChar) {
cell.set(randomChar)
}
}
++iteration
if (iteration < MAX_CELL_ITERATIONS) {
setTimeout(() => loop(line, cell, iteration), 50)
}
}
for (const line of this.lines) {
for (const cell of line.cells) {
setTimeout(() => loop(line, cell), randomNumber(0, 100))
}
}
}
trigger(effect = 'fx') {
if (this.effects && effect in this.effects && !this.isAnimating) {
this.isAnimating = true
const selectedEffect = this.effects[effect]
selectedEffect && selectedEffect()
}
}
}
export const useTypeShuffle = (selector: string) => {
const typeShuffleRef = useRef<TypeShuffle | null>(null)
useEffect(() => {
if (window && document) {
const mainTextElement = document.querySelector(selector) as HTMLElement
if (!mainTextElement) {
return
}
const typeShuffleInstance = new TypeShuffle(mainTextElement)
typeShuffleRef.current = typeShuffleInstance
return () => {
typeShuffleRef.current = null
}
}
}, [selector])
return typeShuffleRef
} Its basically a typeShuffle Effect that uses splitting and spits out the error
|
This worked for me: 'use client'
import 'splitting/dist/splitting.css'
import 'splitting/dist/splitting-cells.css'
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { ReactNode, useEffect } from 'react'
gsap.registerPlugin(ScrollTrigger)
interface Props {
children: ReactNode
}
const AnimateText = ({ children }: Props) => {
let target: any = null
const scroll = (fx17Titles: any) => {
fx17Titles.forEach((title: HTMLElement) => {
const chars = title.querySelectorAll('.char')
chars.forEach((char) =>
gsap.set(char.parentNode, {
perspective: 1000,
})
)
gsap.fromTo(
// targets:
chars,
// from:
{
y: 10,
'will-change': 'opacity, transform',
opacity: 0.7,
rotateX: () => gsap.utils.random(-120, 120),
z: () => gsap.utils.random(-100, 200),
},
// to:
{
y: 0,
z: -12.2,
repeat: 0,
ease: 'none',
opacity: 1,
rotateX: 10,
stagger: 0.1,
scrollTrigger: {
trigger: title,
start: 'top bottom',
end: 'bottom top',
scrub: true,
},
}
)
})
}
useEffect(() => {
const fx17Titles = document.querySelectorAll('.animate-text[data-splitting][data-effect17]')
const splitting = require('Splitting')
splitting({ by: 'chars', target: target })
scroll(fx17Titles)
})
return (
<>
<div
ref={(el) => {
target = el
}}
className={'animate-text'}
data-splitting
data-effect17
>
{children}
</div>
</>
)
}
export default AnimateText ...and then you use it like so: <AnimateText>Some text here</AnimateText> |
I am using this: React.useEffect(() => {
const splitText = async () => {
const { default: Splitting } = await import('splitting');
if (ref.current) {
Splitting({ target: ref.current });
}
};
splitText();
}, []); |
I have this error with the same code as you, this is my package.json: |
I tried to use splitting in my next.js app, but it gives me an error
The text was updated successfully, but these errors were encountered: