dfilatov / vidom-css-animation-group

API for "appearance", "entering" and "leaving" animation via CSS transitions and animations inside Vidom
1 stars 0 forks source link

Uncaught Error: vidom: Detected unexpected attempt to reuse the same node "fragment". #2

Closed LexRiver closed 5 years ago

LexRiver commented 5 years ago

Hello, I'm trying to show and hide some tip with animation. Here is my code

export const Tip = (attrs:Attrs, children:any, context:any) => (
    <div class={cssClassnameTipContainer}>
        {children}
        <CssAnimationGroup enter={GlobalAnimations.bounceInClassname} leave={GlobalAnimations.zoomOutClassname} >
            {attrs.text
                ? <div class={cssClassnameTip} key='key-for-animation'>{attrs.text}</div>
                : null
            }
        </CssAnimationGroup>
    </div>
)

Tip appears correctly with animation, then disappears correctly with animation, but on next show I'm getting the error

Uncaught Error: vidom: Detected unexpected attempt to reuse the same node "fragment".
    at checkReuse (vidom.js:722)
    at FragmentElement.renderToDom (vidom.js:2708)
    at TagElement.renderToDom (vidom.js:1179)
    at FragmentElement.renderToDom (vidom.js:2858)
    at Object.replace (vidom.js:758)
    at TagElement.patch (vidom.js:1495)
    at AnimationGroup.patchComponent [as patch] (vidom.js:2107)
    at ComponentElement.patch (vidom.js:2649)
    at CssAnimationGroup.patchComponent [as patch] (vidom.js:2107)
    at ComponentElement.patch (vidom.js:2516)

What am I doing wrong?

dfilatov commented 5 years ago

Hi, @LexRiver. Could you up vidom-animation-group and vidom-css-animation-group to 0.4.0 and try again? If it doesn't help, please, provide more context.

LexRiver commented 5 years ago

I was trying to reproduce it on a blank project but seems like the problem was in some other place. I was using this.update() but when I rewrite my code using only this.setState() the problem gone. thank you for response.

LexRiver commented 5 years ago

I've figured it out. The error appears only if I try to animate node that I passed as attribute.

Here is my example:

Tip.tsx

import { CssAnimationGroup } from 'vidom-css-animation-group';
import styles from './Tip.m.scss';

interface Attrs{
    text:any
}

export const Tip = (attrs:Attrs, children:any, context:any) => (
    <div>
        {children}
        <CssAnimationGroup enter={styles.bounceIn} leave={styles.zoomOut} >
            {attrs.text &&
                <div class={styles.tip} key='key-for-animation'>{attrs.text}</div>
            }
        </CssAnimationGroup>
    </div>
)

InputValidated.tsx

import { Component, DOMEventHandler } from "vidom";
import { Input } from "./Input";
import { Tip } from "./Tip";

interface Attrs{
    value:string
    onChange:(value:string, isValid:boolean)=>void
    validator:(value:string)=>any
    onKeyUp?:DOMEventHandler<KeyboardEvent>
    defaultErrorMessage:any
}

interface State{
    errorMessage:any
}

export class InputValidated extends Component<Attrs, any, State>{
    onInit(){
    }

    onRender(){
        return (
            <Tip text={this.state.errorMessage?this.attrs.defaultErrorMessage:null}>
                <Input 
                    value={this.attrs.value} 
                    onChange={this.onUserChange} 
                    onKeyUp={this.attrs.onKeyUp} 
                />
            </Tip>
        )
    }

    onUserChange = (newValue:string) => {
        this.setState({errorMessage:this.attrs.validator(newValue)})

    }

}

App.tsx

<InputValidated value={this.state.inputText} onChange={(newValue:string) => {this.setState({inputText:newValue})}} validator={this.validateInput} defaultErrorMessage={<fragment>this is the default error message</fragment>} />

so when I pass fragment defaultErrorMessage={<fragment>this is the default error message</fragment>} and then use it in animation it causes the error. I can give you the whole project if you need.

dfilatov commented 5 years ago

I've tried to reimplement minimal example using your code.

js:

import { Component, mount } from 'vidom';
import { CssAnimationGroup } from 'vidom-css-animation-group';

const Tip = (attrs, children) => (
    <div>
        {children}
        <CssAnimationGroup enter="bounceIn" leave="bounceOut">
            {attrs.text &&
                <div class="tip" key='key-for-animation'>{attrs.text}</div>
            }
        </CssAnimationGroup>
    </div>
)

class InputValidated extends Component {
    onInit(){
        this.setState({errorMessage:this.attrs.validator(this.attrs.value)});
    }

    onRender(){
        return (
            <Tip text={this.state.errorMessage?this.attrs.defaultErrorMessage:null}>
                <input
                    value={this.attrs.value}
                    onChange={(e) => this.onUserChange(e)}
                />
            </Tip>
        )
    }

    onUserChange(e){
        const {value} = e.target;
        this.setState({errorMessage:this.attrs.validator(value)})
        this.attrs.onChange(value);
    }
}

class App extends Component {
    onInit() {
        this.setState({ inputText:'' });
    }

    onRender() {
        return (
            <InputValidated
                value={this.state.inputText}
                onChange={(newValue) => {this.setState({inputText:newValue})}}
                validator={this.validateInput}
                defaultErrorMessage={<fragment>this is the default error message</fragment>}
            />
        )
    }

    validateInput(value) {
        return value.length < 2;
    }
}

mount(document.getElementById('root'), <App/>);

css:

.tip
{
    opacity: 1;
    transition: .5s opacity;
}

.bounceIn
{
    animation: bounceIn .5s;
}

.bounceOut
{
    animation: bounceOut .5s;
}

@keyframes bounceIn
{
    from
    {
        opacity: 0;
    }

    to
    {
        opacity: 1;
    }
}

@keyframes bounceOut
{
    from
    {
        opacity: 1;
    }

    to
    {
        opacity: 0;
    }
}

Everything works fine.

LexRiver commented 5 years ago

src.zip @dfilatov can you please check my project? steps to reproduce:

dfilatov commented 5 years ago

@LexRiver Update vidom to 0.11.1, this problem should disappear

LexRiver commented 5 years ago

@dfilatov that works! thanks!