【问题标题】:How to update state without entering infinite re-render loop in React/Next.js?如何在不进入 React/Next.js 中的无限重新渲染循环的情况下更新状态?
【发布时间】:2020-02-27 01:13:26
【问题描述】:

我有一个播放随机 YouTube 视频的 Next.js 应用。我的应用程序状态如下所示(在 Redux 商店中):

const state = {
    entities: {
        videos: {
            'vidId1': {
                id: 'vidId1',
                title: 'Video 1'
            },
            'vidId2': {
                id: 'vidId2',
                title: 'Video 2'
            },
            'vidId3': {
                id: 'vidId3',
                title: 'Video 3'
            }
        }
    },
    uncategorized: {
        isFetching: false,
        hasNextPage: false,
        nextIndex: 0,
        items: [
            'vidId1',
            'vidId2',
            'vidId3'
        ]
    }
};

然后我的主页如下所示:

// index.js
const Index = () => {
    return (
        <div>
            <h1>Home Page</h1>
            <RandomVideoButton />
        </div>
    );
};

&lt;RandomVideoButton /&gt; 链接到/random。此页面只是从该州获取下一个视频 ID 并重定向到 /videos?id={id}。它看起来像这样:

// random.js
const RandomVideo = () => {
    // Get next video ID
    const nextVideoId = useSelector(state => state.uncategorized.items[state.uncategorized.nextIndex]);

    // Redirect to next video
    const router = useRouter();
    router.push({
        pathname: '/videos',
        query: { id: nextVideoId }
    });

    return (
        <div>Loading video...</div>
    );
};

一旦我在/videos?id={id} 上,该页面将从state.entities.videos 加载视频,然后它会更新state.uncategorized.nextIdnex。这就是问题发生的地方。当我调度操作以更新状态中的下一个视频索引时,我陷入了无限的重新渲染循环。这就是watch.js 的样子:

const WatchVideo = () => {
    // Get video ID from URL query
    const router = useRouter();
    const videoId = router.query.id;

    // Get video
    const { video, activeVideos } = useSelector(state => state.entities.videos[videoId]);

    // Update video index
    const dispatch = useDispatch();
    dispatch({ type: 'INCREMENT_NEXT_INDEX' });

    return (
        <div className="col-12 col-lg-8 col-xl-9">
            {video &&
                <main>
                    <div className="embed-responsive embed-responsive-16by9">
                        <iframe id="player" src={'https://www.youtube-nocookie.com/embed/' + video.id}></iframe>
                    </div>
                    <h1>{video.title}</h1>
                </main>
            }
        </div>
    );
};

我的问题是我不确定如何在仍然能够更新该州的下一个视频索引的同时防止这种情况发生。

【问题讨论】:

    标签: javascript reactjs redux next.js


    【解决方案1】:

    你应该在 react useEffect 钩子中使用调度/路由。 并且您可以使用 videoId 作为 useEffect 依赖项。

    【讨论】:

    • 这个答案为我指明了正确的方向。虽然,我仍然无法在useEffect 中使用useSelectoruseDispatch。我不得不改变我的组件的设置方式。我必须用withRouter(来自Next.js)包装我的组件,并且我必须使用connect 而不是useSelectoruseDispatch(来自Redux)。但是现在在浏览器中单击后退/前进无法按预期工作。点击后退会转到上一个视频,但我无法点击前进。
    • 您可以使用 useReducer 钩子进行状态管理,它应该很容易与路由一起使用,并且 useEffect 钩子 .dispatch 可以从 useReducer 中提取。
    猜你喜欢
    • 1970-01-01
    • 2020-09-14
    • 2016-11-04
    • 2020-04-14
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多