joshwcomeau / react-flip-move

Effortless animation between DOM changes (eg. list reordering) using the FLIP technique.
http://joshwcomeau.github.io/react-flip-move/examples
MIT License
4.09k stars 258 forks source link

Not working in iOS #208

Closed murilonkz closed 6 years ago

murilonkz commented 6 years ago

Hello!

I developed one list using FlipMove and its working very good in Chrome (OSX), but it's not working in Safari (iOS).

The list simply doesnt animate.

Here's a piece of code:

<FlipMove duration={200}>
    { results ? results.map((result) => {
        return (
            <div className={classnames("result", {"selected": result.userVoted})} key={result.answer._id}
                 onClick={this.handleChangeAnswer.bind(this, result.answer)}>
                <div className="option">{ result.answer.option }</div>
                <div className="data">
                    { result.avatars.length > 0 && result.parcialResponses > 0 ?
                        <div className="avatars">
                            <AvatarCounter avatars={result.avatars}/>
                            <div className="vote-counter">{`+${result.parcialResponses} voto(s)`}</div>
                        </div> : null
                    }
                    { result.avatars.length > 0 && result.parcialResponses === 0 ?
                        <div className="avatars">
                            <AvatarCounter avatars={result.avatars}/>
                        </div> : null
                    }
                    { result.avatars.length === 0 && result.totalResponses > 0 ?
                        <div className="avatars">
                            <AvatarCounter avatars={result.avatars} noItemsText={`+${result.totalResponses} voto(s)`}/>
                        </div> : null
                    }
                    { result.avatars.length === 0 && result.totalResponses === 0 ?
                        <div className="avatars">
                            <AvatarCounter avatars={result.avatars} noItemsText={"Nenhum voto registrado"}/>
                        </div> : null
                    }
                    <div className="percentage">{this.state.loadingVoteChange ?
                        <Loading height={27}/> : `${result.percentage.toFixed(2).replace('.', ',')}%` }</div>
                </div>
                <ProgressBar percentage={result.percentage}/>
            </div>
        );
    }) : null }
</FlipMove>

And my events that makes list change:

handleChangeAnswer(answer)
{
    const {results, survey} = this.state;
    const {authUser} = this.props;

    const clickedResult = _.find(results, result => result.userVoted === true);

    // Clicked in same answer
    if (answer._id === clickedResult.answer._id)
        return false;

    // Already clicked in another answer, but its loading
    if (this.state.loadingVoteChange)
        return false;

    this.setState({loadingVoteChange: true});
    SurveyStore.deleteSurveyVotesByUser(survey._id, authUser._id).then(() => {
        this.handleVote(answer._id).then(() => this.setState({loadingVoteChange: false}));
    })
}

async
handleVote(answerId)
{
    if (!this.props.authUser)
        this.props.onUnauthenticatedVote(answerId);

    const survey = this.state.survey;
    const surveyId = survey._id;
    const userId = this.props.authUser._id;

    return SurveyStore.vote(surveyId, answerId, userId)
        .then(() => {
            this.setState({alreadyVoted: true});
            return this._reloadSurvey();
        })
        .then((survey) => {
            this.setState({
                survey: survey,
                results: this._calculateResults(survey)
            });
        })
}

_calculateResults(survey)
{
    const {authUser} = this.props;
    const results = [];

    let index = 0;
    _.forEach(survey.answers, answer => {
        results[index] = {};
        results[index].answer = answer;
        results[index].avatars = _.filter(survey.votes, (vote) => (
        vote.survey_answer === answer._id &&
        vote.user &&
        vote.user._id &&
        vote.user.profile_image)).splice(-6, 6).map(item => item.user.profile_image);
        results[index].totalResponses = _.filter(survey.votes, vote => vote.survey_answer === answer._id).length;
        results[index].parcialResponses = results[index].totalResponses - results[index].avatars.length;
        results[index].percentage = parseFloat(results[index].totalResponses * 100 / survey.votes.length);
        results[index].userVoted = _.filter(survey.votes, vote => vote.survey_answer === answer._id && vote.user && vote.user._id === authUser._id).length > 0;
        index++;
    });

    results.sort((a, b) => a.percentage < b.percentage);

    return results;
}
joshwcomeau commented 6 years ago

Sorry for the delay on this! Was on vacation.

I just tried the demos on my iPhone and they work fine, so I don't think there's a global problem with FlipMove on iOS. Can you try that link on the device that isn't working for you, to check if it's limited to a specific version of mobile safari or something?

oh, maybe it's some conflicting style or something. What are the CSS rules applied to the "result" and "selected" classnames?

If you can create a codesandbox that reproduces the iOS error I can poke at it a bit. Don't have a ton of spare time atm but I could check it out and see if anything jumps out at me! Scanned your code and it seems fine but it's hard to tell without being able to inject some debugging statements.

joshwcomeau commented 6 years ago

Gonna close this, as it's not reproducible for me. I believe it's likely an error in userland.

Will investigate more if a sandbox can be provided!