Skip to content

Instantly share code, notes, and snippets.

@bramblex
Last active May 21, 2020 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bramblex/f71e22eebde7e69b2e6b75ae361cab48 to your computer and use it in GitHub Desktop.
Save bramblex/f71e22eebde7e69b2e6b75ae361cab48 to your computer and use it in GitHub Desktop.
import React, { createContext, useContext, useEffect } from 'react';
import './App.css';
interface LogData {
[key: string]: number | string;
}
interface LogLayerData {
name?: string;
log: LogData;
}
type SendLog = (event: string, log: LogData) => void;
const LogContext = createContext<LogLayerData[]>([]);
function useLog(): [LogData, SendLog] {
const layers = useContext(LogContext);
const baseLog = layers.reduce((p, { log}) => ({...p, ...log}), {});
return [
baseLog, (event, log) => {
console.log(event, {...baseLog, ...log});
},
];
}
function withLog<Props>(Component: React.ComponentType<Props & {log: LogData; sendLog: SendLog}>): React.ComponentType<Props> {
return (props) => {
return (<LogContext.Consumer>
{(layers) => {
const baseLog = layers.reduce((p, { log}) => ({...p, ...log}), {});
return (<Component
{...props}
log={baseLog}
sendLog={(event, log) => {
console.log(event, {...baseLog, ...log});
}}/>);
}}
</LogContext.Consumer>);
};
}
function LogLayer(props: LogLayerData & JSX.ElementChildrenAttribute) {
const {children, ...layer} = props;
const layers = useContext(LogContext);
return (<LogContext.Provider value={layers.concat(layer)}>
{children}
</LogContext.Provider>);
}
// 用 class 组件会比较麻烦
const Test5 = withLog<{}>(class Test5C extends React.PureComponent<{log: LogData; sendLog: SendLog}, {}> {
state = {
};
render() {
return (<div onClick={() => this.props.sendLog('click', { hello: 'click-test5' })}>
Test5 点我
</div>);
}
});
// 使用 hooks 组件非常简单,并且不需要 getPathLog
function Test4() {
const [, sendLog] = useLog();
useEffect(() => {
sendLog('show', {hello: 'show'});
});
return (<div>
<div onClick={() => sendLog('click', {hello: 'click'})}>
Test4 点我
</div>
</div>);
}
function Test3() {
return (<LogLayer name="Test3" log={{ bbb: 131415, ddd: 161718 }}>
<Test4 />
<Test5/>
</LogLayer>);
}
function Test2() {
return (<LogLayer name="Test2" log={{ ddd: 789, eee: 101112}}>
<Test3 />
</LogLayer>);
}
function Test() {
return (<LogLayer name="Test" log={{ aaa: 123, bbb: 456}}>
<Test2 />
</LogLayer>);
}
function App() {
return (
<div>
<div>learn react</div>
<Test />
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment