æ©èœããªã¯ãšã¹ãããã°ãå ±åããŸããïŒ
ãã°
çŸåšã®åäœã¯äœã§ããïŒ
React.memoã§äžèŠãªåã¬ã³ããªã³ã°ãé²ãããã«ïŒuseContextããã¯ïŒã䜿çšããŠã³ã³ããã¹ãAPIããã®ããŒã¿ã«äŸåããããšã¯ã§ããŸãã
çŸåšã®åäœããã°ã§ããå Žåã¯ãåçŸããæé ãšãå¯èœã§ããã°åé¡ã®æå°éã®ãã¢ãæäŸããŠãã ããã 以äžã®JSFiddleïŒhttps://jsfiddle.net/Luktwrdm/ïŒãŸãã¯CodeSandboxïŒhttps://codesandbox.io/s/newïŒã®äŸãžã®ãªã³ã¯ã貌ãä»ããŸãã
React.memo(() => {
const [globalState] = useContext(SomeContext);
render ...
}, (prevProps, nextProps) => {
// How to rely on context in here?
// I need to rerender component only if globalState contains nextProps.value
});
æåŸ ãããåäœã¯äœã§ããïŒ
ã¬ã³ããªã³ã°ãé²ãããã«ãReact.memoã®2çªç®ã®åŒæ°ã®ã³ãŒã«ããã¯ã®ã³ã³ããã¹ãã«äœããã®æ¹æ³ã§ã¢ã¯ã»ã¹ã§ããå¿
èŠããããŸã
ãŸãã¯ãé¢æ°æ¬äœã®reactã³ã³ããŒãã³ãã®å€ãã€ã³ã¹ã¿ã³ã¹ãè¿ãå¯èœæ§ãããã¯ãã§ãã
Reactã®ã©ã®ããŒãžã§ã³ãããã³ã©ã®ãã©ãŠã¶/ OSããã®åé¡ã®åœ±é¿ãåããŸããïŒ
16.8.4
ããã¯èšèšã©ããã«æ©èœããŠããŸãã èå³ãããã°ã httpsïŒ//github.com/facebook/react/issues/14110ã§ããã«ã€ããŠãã£ãšé·ãè°è«ããããŸãã
ãªãããã®çç±ã§ãå€ã«theme
ããããã£ãæã€AppContext
ããã appContextValue.theme
å€æŽã«å¯ŸããŠã®ã¿ExpensiveTree
ãåã¬ã³ããªã³ã°ããããšããŸãã
TLDRã¯ãä»ã®ãšãã3ã€ã®ãªãã·ã§ã³ããããŸãã
å€ãã®ã³ã³ããŒãã³ãã§appContextValue.theme
ãå¿
èŠãªã ãã§ã appContextValue
èªäœãé »ç¹ã«å€æŽãããå Žåã¯ã ThemeContext
ãAppContext
ããåå²ã§ããŸãã
function Button() {
let theme = useContext(ThemeContext);
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}
ããã§ã AppContext
ãå€æŽããŠãã ThemeContext
ã³ã³ã·ã¥ãŒããŒã¯åã¬ã³ããªã³ã°ãããŸããã
ãããæšå¥šãããä¿®æ£ã§ãã ããããã°ãç¹å¥ãªææžã¯å¿ èŠãããŸããã
memo
ã眮ããŸãäœããã®çç±ã§ã³ã³ããã¹ããåå²ã§ããªãå Žåã§ããã³ã³ããŒãã³ãã2ã€ã«åå²ããããå ·äœçãªå°éå ·ãå åŽã®å°éå ·ã«æž¡ãããšã§ãã¬ã³ããªã³ã°ãæé©åã§ããŸãã å€åŽã®ãã®ã¯ã¬ã³ããªã³ã°ããŸãããäœãããªãã®ã§å®äŸ¡ãªã¯ãã§ãã
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return <ThemedButton theme={theme} />
}
const ThemedButton = memo(({ theme }) => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
});
useMemo
1ã€ã®ã³ã³ããŒãã³ãæåŸã«ãã³ãŒããããå°ãåé·ã«ããããšãã§ããŸãããæ»ãå€ãuseMemo
ã§ã©ãããããã®äŸåé¢ä¿ãæå®ããããšã§ãåäžã®ã³ã³ããŒãã³ãã«ä¿æã§ããŸãã ã³ã³ããŒãã³ãã¯åŒãç¶ãåå®è¡ãããŸããããã¹ãŠã®useMemo
å
¥åãåãã§ããå ŽåãReactã¯åããªãŒãåã¬ã³ããªã³ã°ããŸããã
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return useMemo(() => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}, [theme])
}
å°æ¥çã«ã¯ãã£ãšå€ãã®è§£æ±ºçããããããããŸããããããã¯ç§ãã¡ãçŸåšæã£ãŠãããã®ã§ãã
ããã§ãããªãã·ã§ã³1ãæãŸããããšã«æ³šæããŠãã ããã
ããŒããå€æŽãããŠããªãå Žåããããã®ãªãã·ã§ã³ã¯äž¡æ¹ãšãåã®ã¬ã³ããªã³ã°ãã解æŸãããŸãã
@gaearonãã¿ã³ã¯åã§ããã
unstable_Profiler
ãªãã·ã§ã³2ã䜿çšãããšã onRender
ã³ãŒã«ããã¯ãããªã¬ãŒãããŸãããå®éã®ã¬ã³ããªã³ã°ããžãã¯ã¯åŒã³åºãããŸããã å€åç§ã¯äœãééã£ãããšãããŠããã®ã§ããïŒ ãhttps ïŒ //codesandbox.io/s/kxz4o2oyooã https://codesandbox.io/s/00yn9yqzjw
äŸãããæ確ã«ããããã«æŽæ°ããŸããã
stable_Profilerãªãã·ã§ã³2ã䜿çšãããšãonRenderã³ãŒã«ããã¯ãããªã¬ãŒãããŸãããå®éã®ã¬ã³ããªã³ã°ããžãã¯ã¯åŒã³åºãããŸããã å€åç§ã¯äœãééã£ãããšãããŠããã®ã§ããïŒ https://codesandbox.io/s/kxz4o2oyoo
ããããŸãã«ãã®ãªãã·ã§ã³ã®ãã€ã³ãã§ãã :-)
ããããããã®ããã®è¯ã解決çã¯ãã³ãŒã«ããã¯ãtrueãè¿ãå Žåã«ã®ã¿ãã³ã³ããã¹ãããååŸãããŠã³ã³ããŒãã³ããåã¬ã³ããªã³ã°ããå¯èœæ§ãæãããããšã§ãã
useContext(ThemeContext, (contextData => contextData.someArray.length !== 0 ));
ç§ãå®éã«ééããããã¯ã®äž»ãªåé¡ã¯ãã³ã³ããŒãã³ãã«ãã£ãŠè¿ããããã®ãããã¯ã®å åŽãã管çã§ããªãããšã§ã-ã¬ã³ããªã³ã°ãé²æ¢ããããã¡ã¢åãããå€ãè¿ãããããããã§ãã
ã§ããã°ãããã¯æ§æå¯èœã§ã¯ãªãã§ãããã
https://overreacted.io/why-isnt-xa-hook/#not -a-hook-usebailout
ãªãã·ã§ã³4ïŒããŒã¿äŒæã«ã³ã³ããã¹ãã䜿çšãããããŒã¿ãµãã¹ã¯ãªãã·ã§ã³ã«äœ¿çšããŸãã useSubscriptionã䜿çšããŸãïŒãã¹ãŠã®ã±ãŒã¹ãã«ããŒããããã«æžãã®ã¯é£ããããïŒã
åã¬ã³ããªã³ã°ãåé¿ããå¥ã®æ¹æ³ããããŸãã
ãJSXãåã¬ã³ããªã³ã°ã³ã³ããŒãã³ãã®ã¬ãã«ãäžããå¿
èŠããããŸããããããªããšãæ¯ååäœæãããŸãããã
ããããããã®ããã®è¯ã解決çã¯ãã³ãŒã«ããã¯ãtrueãè¿ãå Žåã«ã®ã¿ãã³ã³ããã¹ãããååŸãããŠã³ã³ããŒãã³ããåã¬ã³ããªã³ã°ããå¯èœæ§ãæãããããšã§ãã
useContext(ThemeContext, (contextData => contextData.someArray.length !== 0 ));
ç§ãå®éã«ééããããã¯ã®äž»ãªåé¡ã¯ãã³ã³ããŒãã³ãã«ãã£ãŠè¿ããããã®ãããã¯ã®å åŽãã管çã§ããªãããšã§ã-ã¬ã³ããªã³ã°ãé²æ¢ããããã¡ã¢åãããå€ãè¿ãããããããã§ãã
ããã§true / falseã®ä»£ããã«...ã³ã³ããã¹ãããããŒã¿ããµãã»ããåã§ããIDããŒã¹ã®é¢æ°ãæäŸã§ããŸããïŒ
const contextDataINeed = useContext(ContextObj, (state) => state['keyICareAbout'])
ããã§ãselector fnã®çµæãåãé¢æ°ã®ä»¥åã®çµæãšåäžæ§çã«ç°ãªãå Žåãé€ããŠãuseContextã¯ãã®ã³ã³ããŒãã³ãã«ãããããŸããã
ãã®ã©ã€ãã©ãªã¯ãFacebookãããã¯ãšçµ±åããããã®ãœãªã¥ãŒã·ã§ã³ã§ããå¯èœæ§ãããããšãçºèŠããŸããhttps://blog.axlight.com/posts/super-performant-global-state-with-react-context-and-hooks/
åã¬ã³ããªã³ã°ãåé¿ããå¥ã®æ¹æ³ããããŸãã
ãJSXãåã¬ã³ããªã³ã°ã³ã³ããŒãã³ãã®ã¬ãã«ãäžããå¿ èŠããããŸããããããªããšãæ¯ååäœæãããŸãããã
åé¡ã¯ãäžããäžãžã®åã¬ã³ããªã³ã°ãé²ãããã ãã«ã³ã³ããŒãã³ãããªãŒãåæ§ç¯ããã®ã«ã³ã¹ãããããå¯èœæ§ãããããšã§ãã
@fuleinistæçµçã«ã¯ã
@gaearonäœãã足ããªããã©ããã¯ããããŸãããã2çªç®ãš3çªç®ã®ãªãã·ã§ã³ãè©ŠããŸããããæ£ããæ©èœããŠããŸããã ãããChromeæ¡åŒµæ©èœã®ãã°ã«åå¿ããã ããªã®ãããããšãä»ã®åé¡ãããã®ãââããããªãã ãããç§ã®ç°¡åãªãã©ãŒã ã®äŸã§ãäž¡æ¹ã®å ¥åãåã¬ã³ããªã³ã°ããŠããŸãã ã³ã³ãœãŒã«ã§ã¯ãã¡ã¢ã圌ã®ä»äºãããŠããã®ãããããŸãããDOMã¯åžžã«åã¬ã³ããªã³ã°ãããŸãã 1000åã®ã¢ã€ãã ãè©ŠããŸããããonChangeã€ãã³ããéåžžã«é ããããmemoïŒïŒãã³ã³ããã¹ãã§æ£ããæ©èœããŠããªããšæããŸãã ã¢ããã€ã¹ãããããšãïŒ
ããã¯1000ã¢ã€ãã /ããã¹ãããã¯ã¹ã®ãã¢ã§ãã ãããããã®ãã¢ã§ã¯ãéçºããŒã«ã¯åã¬ã³ããªã³ã°ã衚瀺ããŸããã ãã¹ãããã«ã¯ãããŒã«ã«ã§ãœãŒã¹ãããŠã³ããŒãããå¿ èŠããããŸãïŒ https ïŒ
import React, { createContext, useState, useContext, memo } from "react";
const FormContext = createContext();
const FormProvider = ({ initialValues, children }) => {
const [values, setValues] = useState(initialValues);
const value = {
values,
setValues
};
return <FormContext.Provider value={value}>{children}</FormContext.Provider>;
};
const TextField = memo(
({ name, value, setValues }) => {
console.log(name);
return (
<input
type="text"
value={value}
onChange={e => {
e.persist();
setValues(prev => ({
...prev,
[name]: e.target.value
}));
}}
/>
);
},
(prev, next) => prev.value === next.value
);
const Field = ({ name }) => {
const { values, setValues } = useContext(FormContext);
const value = values[name];
return <TextField name={name} value={value} setValues={setValues} />;
};
const App = () => (
<FormProvider initialValues={{ firstName: "Marr", lastName: "Keri" }}>
First name: <Field name="firstName" />
<br />
Last name: <Field name="lastName" />
</FormProvider>
);
export default App;
äžæ¹ãã³ã³ããã¹ããªãã®ãã®ã¢ãããŒãã¯æ£ããæ©èœããŸããããããã°äžã¯äºæ³ãããé ããªããŸãããå°ãªããšãåã¬ã³ããªã³ã°ã¯åé¡ãããŸããã
import React, { useState, memo } from "react";
import ReactDOM from "react-dom";
const arr = [...Array(1000).keys()];
const TextField = memo(
({ index, value, onChange }) => (
<input
type="text"
value={value}
onChange={e => {
console.log(index);
onChange(index, e.target.value);
}}
/>
),
(prev, next) => prev.value === next.value
);
const App = () => {
const [state, setState] = useState(arr.map(x => ({ name: x })));
const onChange = (index, value) =>
setState(prev => {
return prev.map((item, i) => {
if (i === index) return { name: value };
return item;
});
});
return state.map((item, i) => (
<div key={i}>
<TextField index={i} value={item.name} onChange={onChange} />
</div>
));
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
@marrkeriæåã®ã³ãŒãã¹ããããã«äœãåé¡ã¯ãããŸããã éçºããŒã«ã§åŒ·èª¿è¡šç€ºãããŠããã³ã³ããŒãã³ãã¯ãã³ã³ããã¹ãã䜿çšããField
TextField
ã§ãããã¡ã¢ã³ã³ããŒãã³ãã§ãããareEqualé¢æ°ãå®è£
ãã
codesandboxã®äŸã®ããã©ãŒãã³ã¹ã®åé¡ã¯ãã³ã³ããã¹ãã䜿çšãã1000åã®ã³ã³ããŒãã³ãã«èµ·å ãããšæããŸãã ã³ã³ããã¹ãã䜿çšãã1ã€ã®ã³ã³ããŒãã³ããããšãã°Fields
ã«ãªãã¡ã¯ã¿ãªã³ã°ãããã®ã³ã³ããŒãã³ãããïŒãããã䜿çšããŠïŒå€ããšã«TextField
ãè¿ããŸãã
@marrkeriæåã®ã³ãŒãã¹ããããã«äœãåé¡ã¯ãããŸããã éçºããŒã«ã§åŒ·èª¿è¡šç€ºãããŠããã³ã³ããŒãã³ãã¯ãã³ã³ããã¹ãã䜿çšãã
Field
TextField
ã§ãããã¡ã¢ã³ã³ããŒãã³ãã§ãããareEqualé¢æ°ãå®è£ ããcodesandboxã®äŸã®ããã©ãŒãã³ã¹ã®åé¡ã¯ãã³ã³ããã¹ãã䜿çšãã1000åã®ã³ã³ããŒãã³ãã«èµ·å ãããšæããŸãã ã³ã³ããã¹ãã䜿çšãã1ã€ã®ã³ã³ããŒãã³ããããšãã°
Fields
ã«ãªãã¡ã¯ã¿ãªã³ã°ãããã®ã³ã³ããŒãã³ãããïŒãããã䜿çšããŠïŒå€ããšã«TextField
ãè¿ããŸãã
ããªããèšã£ãããã«ãç§ã¯åãèãã®äžã«ãããŸãã
1ã€ã®ã³ã³ããŒãã³ããžã®ãªãã¡ã¯ã¿ãªã³ã°ã«ã€ããŠã®2çªç®ã®ãã€ã³ããææ¡ããŠããŸãã
ããããreact-reduxãå®å®ããã³ã³ããã¹ãAPIã®å©ç¹ã®äœ¿çšãåæ¢ããããã¯ã«ç§»è¡ãããšãã«çŸåšã®ç¶æ ãã³ã³ããã¹ãã«æž¡ãå¿ èŠããã£ãçç±ã§ããïŒ
ããããã«èŠããŸã
䜿çšæ³ãå¶åŸ¡ããïŒãªãã·ã§ã³2ã3ã«å¿ èŠïŒããã¹ãŠã®å¯èœãªã»ã¬ã¯ã¿ãŒãåæã§ããªãïŒãªãã·ã§ã³1ã«å¿ èŠïŒããããã§ãHooks APIãå ¬éãããå Žåã¯ããããå¯äžã®ãªãã·ã§ã³ã§ããå¯èœæ§ããããŸãã
const MyContext = createContext()
export const Provider = ({children}) => (
<MyContext.provider value={{subscribe: listener => ..., getValue: () => ...}}>
{children}
</MyContext.provider>
)
export const useSelector = (selector, equalityFunction = (a, b) => a === b) => {
const {subscribe, getValue} = useContext(MyContext)
const [value, setValue] = useState(getValue())
useEffect(() => subscribe(state => {
const newValue = selector(state)
if (!equalityFunction(newValue, value) {
setValue(newValue)
}
}), [selector, equalityFunction])
}
@Hypnosphi ïŒããã©ãŒãã³ã¹ã®åé¡ãšã³ã³ããã¹ãã«ãã£ãŠåŒãèµ·ããããæŽæ°ãåé¿ã§ããªãããšã®çµã¿åããã«ãããã³ã³ããã¹ãã§ã®ã¹ãã¢ç¶æ ã®åãæž¡ããåæ¢ãïŒv6å®è£ ïŒãçŽæ¥ã¹ãã¢ãµãã¹ã¯ãªãã·ã§ã³ã«åãæ¿ããŸããïŒããã«ããã v6ã¢ãããŒãã«åºã¥ããŠReact-Reduxããã¯APIãäœæããããšã¯äžå¯èœã§ãïŒã
詳现ã«ã€ããŠã¯ãç§ã®æçš¿ãReact-Reduxã®æŽå²ãšå®è£ ããåç §ããŠãã ããã
ã¹ã¬ãããèªã¿ãŸãããããŸã çåã«æã£ãŠããŸããã³ã³ããã¹ãã®å€æŽæã«æ¡ä»¶ä»ãã§åã¬ã³ããªã³ã°ããããã«ä»æ¥å©çšã§ãããªãã·ã§ã³ã¯ãäžèšã®ããªãã·ã§ã³1 2 3 4ãã ãã§ããïŒ ããã«å ¬åŒã«å¯ŸåŠããããã«äœæ¥äžã®ä»ã®äœãããããŸããããããšãã4ã€ã®è§£æ±ºçãã¯ååã«èš±å®¹ã§ãããšèããããŠããŸããïŒ
ç§ã¯å¥ã®ã¹ã¬ããã§æžãããã念ã®ããã ããã_éå
¬åŒ_ã®åé¿çã§ãã
ãŠãŒã¶ãŒã©ã³ãã®useContextSelectorããããŒã¶ã«ãšuse-context-selectorã©ã€ãã©ãªã
æ£çŽãªãšãããããã¯ç§ãã¡ã奚å±ãããŠããããã«ããã¬ãŒã ã¯ãŒã¯ãé¢æ°ãããã¯ã«å®å šã«å ¥ãæºåãã§ããŠããªãããšãç§ã«æãããŸãã ã¯ã©ã¹ãšã©ã€ããµã€ã¯ã«ã¡ãœããã䜿çšãããšãããããå¶åŸ¡ããããã®æŽç¶ãšããæ¹æ³ããããŸããããããã¯ã䜿çšãããšãæ§æãã¯ããã«èªã¿ã«ãããªããŸãã
ãªãã·ã§ã³3ã¯æ©èœããŠããªãããã§ãã ç§ã¯äœãééã£ãããšãããŠããŸããïŒ https://stackblitz.com/edit/react-w8gr8z
@ããŒãã£ã³ãç§ã¯ããã«åæããŸããã
ããã¯ãã¿ãŒã³ã¯ãããæŽçãããããã¥ã¡ã³ããšã³ãŒãã§èªã¿åãããšãã§ããŸã
æ§é ãšReactã®ã¯ã©ã¹ãšã©ã€ããµã€ã¯ã«ã¯ãã¹ãŠæ©èœã«çœ®ãæãå¯èœã§ã
åçã®ãã®ã
æ®å¿µãªããããªã¢ã¯ãã£ããã¿ãŒã³ã¯Reactãä»ããŠéæããããšã¯ã§ããŸãã
Reactã¯ã©ã¹ãŸãã¯ããã¯ã®ããããã
9:44ããŒãã£ã³Genevã§åã2020幎1æ11æ¥ã«ã¯[email protected]
æžããŸããïŒ
æ£çŽãªãšãããããã¯ãã¬ãŒã ã¯ãŒã¯ãæºåãã§ããŠããªãããšãç§ã«æãããŸã
ç§ãã¡ã奚å±ãããŠããããã«ãé¢æ°ãšããã¯ã«å®å šã«çµã¿èŸŒãŸããŠããŸãã ã¯ã©ã¹ãã
ãããŠãããªãããããã®ãã®ãå¶åŸ¡ããããã®ãã¡ããšããæ¹æ³ãæã£ãŠããã©ã€ããµã€ã¯ã«ã¡ãœãããš
ããã¯ã䜿çšãããšãæ§æãã¯ããã«èªã¿ã«ãããªããŸãâ
ããªããèšåãããã®ã§ãããªãã¯ãããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/facebook/react/issues/15156?email_source=notifications&email_token=AAI4DWUJ7WUXMHAR6F2KVXTQ5D25TA5CNFSM4G7UEEO2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN
ãŸãã¯è³Œèªã解é€ãã
https://github.com/notifications/unsubscribe-auth/AAI4DWUCO7ORHV5OSDCE35TQ5D25TANCNFSM4G7UEEOQ
ã
@mgenevãªãã·ã§ã³3ã¯ãåã®åã¬ã³ããªã³ã°ãé²ããŸãïŒ <ExpensiveTree />
ãååã¯ããèªäœãè¡šããŸãïŒ
@Hypnosphiããããšããããã¯æ£ããã£ãã
https://stackblitz.com/edit/react-ycfyye
æžãçŽãããšãããå®éã®ã¬ã³ããªã³ã°ïŒè¡šç€ºïŒã³ã³ããŒãã³ãã¯åã¬ã³ããªã³ã°ãããŸãããããã¹ãŠã®ã³ã³ãããŒïŒã³ã³ããã¹ãæ¥ç¶ïŒã¯ã䜿çšãããŠãããã©ããã«é¢ä¿ãªããã³ã³ããã¹ãäžã®propã®å€æŽæã«ã¬ã³ããªã³ã°ãããŸãã ä»ç§ãèŠãããšãã§ããå¯äžã®ãªãã·ã§ã³ã¯ãã³ã³ããã¹ãã®åå²ãéå§ããããšã§ãããããã€ãã®ãã®ã¯æ¬åœã«ã°ããŒãã«ã§ãããæé«ã¬ãã«ã§ã©ããããããããã®ãããããå€æŽãããšãã¢ããªå šäœã§ãã¹ãŠã®ã³ã³ãããŒãèµ·åããŸãããããããã©ãŒãã³ã¹ã«ã©ã®ããã«åœ¹ç«ã€ããç解ããŠãã ãã...
ããã©ãŒãã³ã¹ã®é«ãæ¹æ³ã§ãããè¡ãæ¹æ³ã®è¯ãäŸã¯ã©ããã«ãããŸããïŒ å ¬åŒããã¥ã¡ã³ãã¯æ¬åœã«éãããŠããŸã
ããªãã¯ç§ã®ãªãã·ã§ã³4ãè©Šãããšãã§ããŸããããã¯åºæ¬çã«react-reduxãå
éšã§è¡ãããšã§ã
https://github.com/facebook/react/issues/15156#issuecomment -546703046
subscribe
é¢æ°ãå®è£
ããã«ã¯ãObservablesãEventEmitterãªã©ã䜿çšããããåºæ¬çãªãµãã¹ã¯ãªãã·ã§ã³ããžãã¯ãèªåã§äœæããŸãã
function StateProvider({children}) {
const [state, dispatch] = useReducer(reducer, initialState)
const listeners = useRef([])
const subscribe = listener => {
listeners.current.push(listener)
}
useEffect(() => {
listeners.current.forEach(listener => listener(state)
}, [state])
return (
<DispatchContext.Provider value={dispatch}>
<SubscribeContext.Provider value={{subscribe, getValue: () => state}}>
{children}
</SubscribeContext.Provider>
</DispatchContext.Provider>
);
}
èå³ã®ããæ¹ã®ããã«ããã®ãããã¯ã«ããããé¢é£ããããŸããŸãªã©ã€ãã©ãªã®æ¯èŒã瀺ããŸãã
https://github.com/dai-shi/will-this-react-global-state-work-in-concurrent-mode
ç§ã®æè¿ã®åãçµã¿ã¯ã次ã®äžŠè¡ã¢ãŒãã§éèŠã«ãªãuseTransition
ã䜿çšããç¶æ
åå²ã®ãµããŒãã確èªããããšã§ãã
åºæ¬çã«ãReactã®ç¶æ
ãšã³ã³ããã¹ããéåžžã®æ¹æ³ã§äœ¿çšããã°åé¡ãããŸããã ïŒãã以å€ã®å Žåã¯ãããªãã¯ãå¿
èŠã§ããããšãã°ãããã§ããïŒ
ããããšã@ dai-shiç§ã¯ããªãã®ããã±ãŒãžãæ¬åœã«å¥œãã§ãããããæ¡çšããããšãæ€èšããŠããŸãã
@ dai-shiããã«ã¡ã¯ãç§ã¯ããªãã®react-tracked
libãèŠã€ããŸããããããçŽæã©ããã«ã³ã³ããã¹ãã®ããã©ãŒãã³ã¹ã®åé¡ã解決ãããªããããã¯æ¬åœã«è¯ãããã§ãã ããã§ãå®éã®ãã®ã§ããããããšãä»ã®ãã®ã䜿çšããæ¹ãè¯ãã§ããïŒ ããã§ã¯ããã®äœ¿çšäŸã瀺ããŠããŸãããŸãã use-reducer-async
httpsïŒ//github.com/dai-shi/react-tracked/blob/master/examples/12_async/src/storeã䜿çšããŠããã«ãŠã§ã¢ã¬ãã«ãäœæããæ¹æ³ã瀺ããŠãuseReducer
å
ãã dispatch
éåæããã«ãŠã§ã¢ã®ç§èªèº«ã®ãã®ãšãã䜿çšããŠContext
ããçç±ã¯ã³ã³ããã¹ãã®æãè¿ãã®å°æ¥ã®ã¬ã³ããªã³ã°ã®ããã©ãŒãã³ã¹ã®åé¡ã®ããã«å¿é
ããŸãã
@bobrosoft react-tracked
ã¯ããªãå®å®ããŠãããšæããŸãïŒç¢ºãã«1ã€ã®éçºè
補åãšããŠïŒã ãã£ãŒãããã¯ã¯å€§æè¿ã§ããããããããšã§ãã©ã€ãã©ãªãæ¹åãããŸãã çŸåšãå
éšçã«ã¯Reactã®ææžåãããŠããªãæ©èœã䜿çšããŠãããå°æ¥çã«ã¯ããåªããããªããã£ãã«çœ®ãæããããšãã§ãããšæããŸãã use-reducer-async
ã¯ãééãã®ãªãåçŽãªã·ã³ã¿ãã¯ã¹ã·ã¥ã¬ãŒã®ãããªãã®ã§ãã
ãã®HoCã¯ç§ã®ããã«åããïŒ
`` `` ``
import Reactã{useMemoãReactElementãFC} from'react ';
'lodash / reduce'ããreduceãã€ã³ããŒãããŸãã
ã¿ã€ãã»ã¬ã¯ã¿ãŒ=ïŒã³ã³ããã¹ãïŒä»»æïŒ=>ä»»æ;
ã€ã³ã¿ãŒãã§ã€ã¹SelectorObject {
}
const withContext =ïŒ
ã³ã³ããŒãã³ãïŒFCã
ã³ã³ããã¹ãïŒä»»æã
ã»ã¬ã¯ã¿ãŒïŒSelectorObjectã
ïŒïŒFC => {
returnïŒpropsïŒanyïŒïŒReactElement => {
const Consumer =ïŒ{context}ïŒanyïŒïŒReactElement => {
const contextProps = reduceïŒ
ã»ã¬ã¯ã¿ãŒã
ïŒaccïŒanyãselectorïŒSelectorãkeyïŒstringïŒïŒany => {
const value =ã»ã¬ã¯ã¿ãŒïŒã³ã³ããã¹ãïŒ;
acc [key] =å€;
accãè¿ããŸãã
}ã
{}ã
ïŒ;
useMemoïŒãè¿ã
ïŒïŒïŒReactElement =>
[... Object.valuesïŒpropsïŒã... Object.valuesïŒcontextPropsïŒ]ã
ïŒ;
};
æ»ã ïŒ
{ïŒã³ã³ããã¹ãïŒä»»æïŒïŒReactElement =>
ïŒ;
};
};
ããã©ã«ãã®withContextããšã¯ã¹ããŒãããŸãã
`` `` ``
䜿çšäŸïŒ
export default withContext(Component, Context, {
value: (context): any => context.inputs.foo.value,
status: (context): any => context.inputs.foo.status,
});
ããã¯ãreduxmapStateToPropsãšåçã®ã³ã³ããã¹ããšèŠãªãããšãã§ããŸã
reduxã®connectïŒïŒãšã»ãŒåãããã«ããã¯ãäœæããŸãã
const withContext = (
context = createContext(),
mapState,
mapDispatchers
) => WrapperComponent => {
function EnhancedComponent(props) {
const targetContext = useContext(context);
const { ...statePointers } = mapState(targetContext);
const { ...dispatchPointers } = mapDispatchers(targetContext);
return useMemo(
() => (
<WrapperComponent {...props} {...statePointers} {...dispatchPointers} />
),
[
...Object.values(statePointers),
...Object.values(props),
...Object.values(dispatchPointers)
]
);
}
return EnhancedComponent;
};
å®è£ ïŒ
const mapActions = state => {
return {};
};
const mapState = state => {
return {
theme: (state && state.theme) || ""
};
};
export default connectContext(ThemeContext, mapState, mapActions)(Button);
æŽæ°ïŒæçµçã«ãåçãªã¹ããŒïŒããŠã¹ã®ç§»åæïŒã䜿çšããŠãé«éã§å€åãã詳现ãªããŒã¿ãååŸããããã«EventEmitterã«åãæ¿ããŸããã ç§ã¯ãããä»äºã®ããã®ããè¯ãããŒã«ã§ããããšã«æ°ã¥ããŸããã ã³ã³ããã¹ãã¯ãäžè¬çã«ããŒã¿ãå ±æããã®ã«æé©ã§ãããé«ããªãã¬ãã·ã¥ã¬ãŒãã§ã¯é©ããŠããŸããã
宣èšçã«ãµãã¹ã¯ã©ã€ãããããã³ã³ããã¹ãã«ãµãã¹ã¯ã©ã€ãããªãããšããããšã«ãªããŸãããïŒ useContextïŒïŒã䜿çšããå¥ã®ã³ã³ããŒãã³ãã§æ¡ä»¶ä»ãã§ã©ããããŸãã
äž»ãªèŠä»¶ã¯ãå éšã³ã³ããŒãã³ããç¶æ ãæã€ããšãã§ããªãããšã§ããããã¯ãåå²ã®ããã«å®è³ªçã«å¥ã®ã€ã³ã¹ã¿ã³ã¹ã«ãªãããã§ãã ãŸãã¯ãã³ã³ããŒãã³ããäºåã«ã¬ã³ããªã³ã°ããŠãããcloneElementã䜿çšããŠå°éå ·ãæŽæ°ããããšãã§ããŸãã
äžéšã®ã³ã³ããŒãã³ãã¯ãã¬ã³ããªã³ã°ã®ã³ã³ããã¹ããšã¯é¢ä¿ãããŸãããããããããå€ãèªã¿åããå¿
èŠããããŸãã ç§ã¯äœãæ¬ ããŠããŸããïŒ
Context._currentValueã¯æ¬çªç°å¢ã§å®å šã«äœ¿çšã§ããŸããïŒ
å¯èœãªéãã¬ã³ããªã³ã°ãå®äŸ¡ãªã³ã³ããã¹ãã«ã³ã³ããŒãã³ãããµãã¹ã¯ã©ã€ãããããšããŠããŸãã ãããããã®åŸãç§ã¯ãsphagettiã³ãŒãã䜿çšããå€ãæ¹æ³ã®ããã«å°éå ·ãæž¡ãããæŽæ°ã«è«ççãªãã®ããªãå Žåã«æŽæ°ããµãã¹ã¯ã©ã€ãããªãããã«ã¡ã¢ã䜿çšããããšã«æ°ä»ããŸããã ã¡ã¢ãœãªã¥ãŒã·ã§ã³ã¯ãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ãã³ã³ããã¹ãã«äŸåããå Žåã«é©ããŠããŸããããã以å€ã®å Žåã¯...
@ vamshi9666ããªãã¯ããããããã䜿ã£ãŠããŸããïŒ ããªãã¯ããªãã®ã¢ãããŒãã®è³åŠäž¡è«ã«æ°ä»ãããšãã§ããŸãããïŒ ããã¯å€§å¥œãã§ãã ç§ã¯reduxãšã®é¡äŒŒæ§ã奜ãã§ãããã³ã³ããã¹ããšããŠã¢ããªã®ç¶æ 管çãšããžãã¯ãèªç±ã«èšè¿°ã§ããæ¹æ³ãæ°ã«å ¥ã£ãŠããŸã
https://recoiljs.org/ããã®åé¡ã®è¯ã解決çã§ããããšãããããŸããã Reactã«çµ±åããã°çŽ æŽããããšæããŸãã
@ vamshi9666ããªãã¯ããããããã䜿ã£ãŠããŸããïŒ ããªãã¯ããªãã®ã¢ãããŒãã®è³åŠäž¡è«ã«æ°ä»ãããšãã§ããŸãããïŒ ããã¯å€§å¥œãã§ãã ç§ã¯reduxãšã®é¡äŒŒæ§ã奜ãã§ãããã³ã³ããã¹ããšããŠã¢ããªã®ç¶æ 管çãšããžãã¯ãèªç±ã«èšè¿°ã§ããæ¹æ³ãæ°ã«å ¥ã£ãŠããŸã
ç§ã¯ããã1ã€ã®å Žæã§ã®ã¿äœ¿çšããŸãããæåã®ç®æšã¯ãç¶æ 管çãjsxããåé¢ããããšã§ãããå®åæãäœæããããšã§ããããŸããã ãã®ããããã¥ãŒããŒã·ã§ã³æ©èœãæ¡åŒµãããšãreduxã®ã¬ãã¥ãŒãµãŒãšã¢ã¯ã·ã§ã³ã¯ãªãšãŒã¿ãŒã®ãã¿ãŒã³ã«éåžžã«ãã䌌ãŠããŸããã ããã¯ããã«è¯ãã§ãã ããããå®éã«ã¯ãã§ã«ããã«ããã®ã«ãäœããåçºæããæå³ã¯ããããŸããã
æãåèã«ãªãã³ã¡ã³ã
ããã¯èšèšã©ããã«æ©èœããŠããŸãã èå³ãããã°ã httpsïŒ//github.com/facebook/react/issues/14110ã§ããã«ã€ããŠãã£ãšé·ãè°è«ããããŸãã
ãªãããã®çç±ã§ãå€ã«
theme
ããããã£ãæã€AppContext
ãããappContextValue.theme
å€æŽã«å¯ŸããŠã®ã¿ExpensiveTree
ãåã¬ã³ããªã³ã°ããããšããŸããTLDRã¯ãä»ã®ãšãã3ã€ã®ãªãã·ã§ã³ããããŸãã
ãªãã·ã§ã³1ïŒæšå¥šïŒïŒäžç·ã«å€æŽãããªãã³ã³ããã¹ããåå²ãã
å€ãã®ã³ã³ããŒãã³ãã§
appContextValue.theme
ãå¿ èŠãªã ãã§ãappContextValue
èªäœãé »ç¹ã«å€æŽãããå Žåã¯ãThemeContext
ãAppContext
ããåå²ã§ããŸããããã§ã
AppContext
ãå€æŽããŠããThemeContext
ã³ã³ã·ã¥ãŒããŒã¯åã¬ã³ããªã³ã°ãããŸããããããæšå¥šãããä¿®æ£ã§ãã ããããã°ãç¹å¥ãªææžã¯å¿ èŠãããŸããã
ãªãã·ã§ã³2ïŒã³ã³ããŒãã³ãã2ã€ã«åå²ãããã®éã«
memo
ã眮ããŸãäœããã®çç±ã§ã³ã³ããã¹ããåå²ã§ããªãå Žåã§ããã³ã³ããŒãã³ãã2ã€ã«åå²ããããå ·äœçãªå°éå ·ãå åŽã®å°éå ·ã«æž¡ãããšã§ãã¬ã³ããªã³ã°ãæé©åã§ããŸãã å€åŽã®ãã®ã¯ã¬ã³ããªã³ã°ããŸãããäœãããªãã®ã§å®äŸ¡ãªã¯ãã§ãã
ãªãã·ã§ã³3ïŒå éšã«
useMemo
1ã€ã®ã³ã³ããŒãã³ãæåŸã«ãã³ãŒããããå°ãåé·ã«ããããšãã§ããŸãããæ»ãå€ã
useMemo
ã§ã©ãããããã®äŸåé¢ä¿ãæå®ããããšã§ãåäžã®ã³ã³ããŒãã³ãã«ä¿æã§ããŸãã ã³ã³ããŒãã³ãã¯åŒãç¶ãåå®è¡ãããŸããããã¹ãŠã®useMemo
å ¥åãåãã§ããå ŽåãReactã¯åããªãŒãåã¬ã³ããªã³ã°ããŸãããå°æ¥çã«ã¯ãã£ãšå€ãã®è§£æ±ºçããããããããŸããããããã¯ç§ãã¡ãçŸåšæã£ãŠãããã®ã§ãã
ããã§ãããªãã·ã§ã³1ãæãŸããããšã«æ³šæããŠãã ããã