我想更改子組件的內容以回應另一個子組件中的用戶事件,而不會導致父組件重新渲染。
我已經嘗試將子狀態設定器存盤到父變數中,但它沒有在子節點全部呈現時定義,所以它不起作用。
有沒有一種最小的方法來完成這個(不安裝狀態管理庫)?
ChildToChild.tsx
import React, {
Dispatch,
SetStateAction,
useEffect,
useRef,
useState,
} from "react";
export default function ChildToChild() {
const renderCounter = useRef(0);
renderCounter.current = renderCounter.current 1;
let setChildOneContent;
const childOneContentController = (
setter: Dispatch<SetStateAction<string>>
) => {
setChildOneContent = setter;
};
return (
<div>
<h1>Don't re-render me please</h1>
<p>No. Renders: {renderCounter.current}</p>
<ChildOne childOneContentController={childOneContentController} />
<ChildTwo setChildOneContent={setChildOneContent} />
</div>
);
}
function ChildOne({
childOneContentController,
}: {
childOneContentController: (setter: Dispatch<SetStateAction<string>>) => void;
}) {
const [content, setContent] = useState("original content");
useEffect(() => {
childOneContentController(setContent);
}, [childOneContentController, setContent]);
return (
<div>
<h2>Child One</h2>
<p>{content}</p>
</div>
);
}
function ChildTwo({
setChildOneContent,
}: {
setChildOneContent: Dispatch<SetStateAction<string>> | undefined;
}) {
return (
<div>
<h2>Child Two</h2>
<button
onClick={() => {
if (setChildOneContent) setChildOneContent("content changed");
}}
>
Change Child One Content
</button>
</div>
);
}
uj5u.com熱心網友回復:
你應該能夠通過
- 在子組件中使用狀態
- 在父組件中使用回呼函式呼叫
setState子組件的函式。這將觸發孩子的重新渲染,而不是它自己(父母)的重新渲染。
演示:https : //codesandbox.io/s/child-re-rendering-only-x37ol
uj5u.com熱心網友回復:
對于一次性,您可以使用以下(另一個ref來存盤和使用ChildOne setContent:
import React, {
Dispatch,
SetStateAction,
useEffect,
useRef,
useState
} from "react";
function ChildOne({
setChildOneRef
}: {
setChildOneRef: React.MutableRefObject<React.Dispatch<
React.SetStateAction<string>
> | null>;
}) {
const [content, setContent] = useState("original content");
useEffect(() => {
setChildOneRef.current = setContent;
}, [setChildOneRef]);
return (
<div>
<h2>Child One</h2>
<p>{content}</p>
</div>
);
}
function ChildTwo({
setChildOneRef
}: {
setChildOneRef: React.MutableRefObject<React.Dispatch<
React.SetStateAction<string>
> | null>;
}) {
return (
<div>
<h2>Child Two</h2>
<button
onClick={() => {
setChildOneRef.current?.("content changed");
}}
>
Change Child One Content
</button>
</div>
);
}
export function ChildToChild() {
const renderCounter = useRef(0);
renderCounter.current = renderCounter.current 1;
const setChildOneRef = useRef<Dispatch<SetStateAction<string>> | null>(null);
return (
<div>
<h1>Don't re-render me please</h1>
<p>No. Renders: {renderCounter.current}</p>
<ChildOne setChildOneRef={setChildOneRef} />
<ChildTwo setChildOneRef={setChildOneRef} />
</div>
);
}
如果這種模式在您的代碼中很常見,您可能仍想使用狀態管理庫或評估“孩子”是否應該真正分開。
uj5u.com熱心網友回復:
您可以通過將回呼傳遞給第一個孩子,然后將其傳遞給下一個孩子,將鉤子傳遞回父級。這是漂亮的草圖,但它是可能的。我還沒有驗證這不會重新渲染父級,但我相當肯定它不會考慮掛鉤附加到子級而不是父級。
import './App.css';
import { useState } from "react";
const Child1 = ( stateCb ) => {
const [count, setCount] = useState( 0 )
stateCb( count, setCount )
return <div>
{count}
</div>
}
const Child2 = ( count, setCount ) => {
return <button onClick={() => setCount( count 1 )}>
clickme
</button>
}
function App() {
let count, setCount
return (
<div className="App">
{Child1(( c, sc ) => {
count = c;
setCount = sc
})}
{Child2(count, setCount)}
</div>
);
}
export default App;
uj5u.com熱心網友回復:
該事件可以在 RxJS 主題上傳播,如果需要則帶有值。
// in parent
// const subject = new rxjs.Subject();
const subject = { // or create lightweight alternative
nextHandlers: [],
next: function(value) {
this.nextHandlers.forEach(handler => handler(value));
},
subscribe: function(nextHandler) {
this.nextHandlers.push(nextHandler);
return {
unsubscribe: () => {
this.nextHandlers.splice(
this.nextHandlers.indexOf(nextHandler),
1
);
}
};
}
};
// provide next method to the childOne
onClick={value => subject.next(value)}
// provide subscribe method to the childTwo
subscribeOnClick={(nextHandler) => subject.subscribe(nextHandler)}
// in childTwo
useEffect(() => {
const subscription = subscribeOnClick(value => setContent(value));
return () => subscription.unsubscribe();
}, [subscribeOnClick]);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/346980.html
標籤:javascript 反应 打字稿
下一篇:對物件進行排序并洗掉重復項
