React.StrictMode 和 createRoot 影响我的 UI 渲染。

huangapple go评论55阅读模式
英文:

React.StrictMode and createRoot influence my UI render

问题

I am new to react. This is a generated code block in my project by create-react-app

const root = createRoot(container);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);```
Now I am using gsap to render anime. There is a disgusting blank block at the top of the page. Finally I found out the reason is these code, I also find out the solutions, but I do not know why.
##### 1. `ReactDOM.render` with `React.StrictMode` success.
##### 2. `createRoot.render(<App />)` success.
##### 3. `createRoot.render()` with `React.StrictMode` FAILED.
Here is the [project][1]

Can anyone explain these differences?

---------Edit-----------
context is a solution, but it's broken again after adding another `<div id='img2'>` for animation

  [1]: https://codesandbox.io/s/friendly-sunset-lfp4gs?file=/src/index.js:519-537

<details>
<summary>英文:</summary>

I am new to react. This is a generated code block in my project by create-react-app

const container = document.getElementById("root");
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Now I am using gsap to render anime. There is a disgusting blank block at the top of the page. Finally I found out the reason is these code, I also find out the solutions, but I do not know why.
##### 1. `ReactDOM.render` with `&lt;React.StrictMode&gt;` success.
##### 2. `createRoot.render(&lt;App /&gt;)` success.
##### 3. `createRoot.render()` with `&lt;React.StrictMode&gt;` FAILED.
Here is the [project][1]
Can anyone explain these differences?

---------Edit-----------  
context is a solution, but it&#39;s broken again after add another `&lt;div id=&#39;img2&#39;&gt;` for animation

  [1]: https://codesandbox.io/s/friendly-sunset-lfp4gs?file=/src/index.js:519-537

</details>


# 答案1
**得分**: 1

从[`gsap.context()`](https://greensock.com/docs/v3/GSAP/gsap.context())文档中:

&gt; `gsap.context()` 解决了 React 18 中 "Strict Mode 中 `useEffect()` 双重调用" 问题,通常会破坏 `from()` 逻辑 - 只需在 `useEffect()` 清理函数中对上下文调用 `revert()`:

```ts
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import React, { useEffect, useRef } from 'react';
import './App.css';
gsap.registerPlugin(ScrollTrigger);

function App() {
	const ref = useRef(null);

	useEffect(() => {
		const ele = ref.current;
		let ctx = gsap.context(() => {
			gsap.fromTo(
				ele.querySelector('#img1'),
				{
					opacity: 0,
					x: -100,
				},
				{
					opacity: 1,
					x: 100,
					scrollTrigger: {
						trigger: ele.querySelector('.screen1'),
						start: 'top top',
						end: 'bottom center',
						scrub: true,
						pin: true,
						markers: true,
					},
				},
			);
		});
		return () => ctx.revert();
	}, []);

	return (
		<div ref={ref}>
			<div className="screen1">
				<div id="img1">加载图片</div>
			</div>
			<div className="screen2"></div>
			<div className="screen3"></div>
			<div className="screen4"></div>
		</div>
	);
}

export default App;

CodeSandbox

英文:

From the gsap.context() documentation:

> gsap.context() works around the React 18 "double-call of useEffect() in Strict Mode" issue that normally breaks from() logic - just call revert() on the Context in your useEffect() cleanup function:

import { gsap } from &#39;gsap&#39;;
import { ScrollTrigger } from &#39;gsap/ScrollTrigger&#39;;
import React, { useEffect, useRef } from &#39;react&#39;;
import &#39;./App.css&#39;;
gsap.registerPlugin(ScrollTrigger);

function App() {
	const ref = useRef(null);

	useEffect(() =&gt; {
		const ele = ref.current;
		let ctx = gsap.context(() =&gt; {
			gsap.fromTo(
				ele.querySelector(&#39;#img1&#39;),
				{
					opacity: 0,
					x: -100,
				},
				{
					opacity: 1,
					x: 100,
					scrollTrigger: {
						trigger: ele.querySelector(&#39;.screen1&#39;),
						start: &#39;top top&#39;,
						end: &#39;bottom center&#39;,
						scrub: true,
						pin: true,
						markers: true,
					},
				},
			);
		});
		return () =&gt; ctx.revert();
	}, []);

	return (
		&lt;div ref={ref}&gt;
			&lt;div className=&quot;screen1&quot;&gt;
				&lt;div id=&quot;img1&quot;&gt;load img&lt;/div&gt;
			&lt;/div&gt;
			&lt;div className=&quot;screen2&quot;&gt;&lt;/div&gt;
			&lt;div className=&quot;screen3&quot;&gt;&lt;/div&gt;
			&lt;div className=&quot;screen4&quot;&gt;&lt;/div&gt;
		&lt;/div&gt;
	);
}

export default App;

codesandbox

答案2

得分: 0

使用ScrollTrigger的方式如下:

const main = useRef(null);
const tl = useRef();

useLayoutEffect(() => {
    let ctx = gsap.context(() => {
        tl.current = gsap.timeline({
            scrollTrigger: {
                trigger: '.screen1',
                start: 'top top',
                end: '+=200',
                scrub: true,
                pin: true,
                markers: true,
            }
        })
            .fromTo(
                '#img1',
                {
                    opacity: 0,
                    x: 0
                },
                {
                    opacity: 1,
                    x: '20%',
                })
            .fromTo(
                '#img2',
                {
                    opacity: 0,
                    x: '100%' 
                },
                {
                    opacity: 1,
                    x: '80%',
                })
    }, main);
    return () => ctx.revert();
}, [])
英文:

Should use ScrollTrigger in this way

    const main = useRef(null);
const tl = useRef()
useLayoutEffect(() =&gt; {
let ctx = gsap.context(() =&gt; {
tl.current = gsap.timeline({
scrollTrigger: {
trigger: &#39;.screen1&#39;,
start: &#39;top top&#39;,
end: &#39;+=200&#39;,
scrub: true,
pin: true,
markers: true,
}
})
.fromTo(
&#39;#img1&#39;,
{
opacity: 0,
x: 0
},
{
opacity: 1,
x: &#39;20%&#39;,
})
.fromTo(
&#39;#img2&#39;,
{
opacity: 0,
x: &#39;100%&#39; 
},
{
opacity: 1,
x: &#39;80%&#39;,
})
}, main);
return () =&gt; ctx.revert();
}, [])

huangapple
  • 本文由 发表于 2023年7月3日 11:59:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76601768.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定