├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github
├── CODEOWNERS
└── workflows
│ └── main.yml
├── .gitignore
├── .husky
└── pre-commit
├── .nvmrc
├── .storybook
├── main.js
└── preview.js
├── LICENSE
├── README.md
├── demo
├── index.html
└── index.tsx
├── jest.config.ts
├── package-lock.json
├── package.json
├── react-log-hook-screenshot.png
├── src
├── constants.ts
├── index.stories.tsx
├── index.test.tsx
├── index.tsx
├── types.ts
├── utils.test.ts
└── utils.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | node_modules/
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true,
5 | "node": true
6 | },
7 | "extends": [
8 | "plugin:react/recommended",
9 | "standard-with-typescript"
10 | ],
11 | "overrides": [],
12 | "parserOptions": {
13 | "project": "./tsconfig.json"
14 | },
15 | "plugins": [
16 | "react",
17 | "prettier"
18 | ],
19 | "rules": {
20 | "prettier/prettier": [
21 | "error",
22 | {
23 | "singleQuote": true,
24 | "semi": false,
25 | "bracketSpacing": true,
26 | "trailingComma": "all",
27 | "bracketSameLine": true
28 | }
29 | ],
30 | "react/prop-types": "off",
31 | "comma-dangle": "off",
32 | "@typescript-eslint/comma-dangle": [
33 | "error",
34 | {
35 | "arrays": "always-multiline",
36 | "objects": "always-multiline",
37 | "imports": "always-multiline",
38 | "exports": "always-multiline",
39 | "functions": "always-multiline",
40 | "enums": "always-multiline"
41 | }
42 | ],
43 | "space-before-function-paren": "off",
44 | "@typescript-eslint/space-before-function-paren": "off",
45 | "@typescript-eslint/strict-boolean-expressions": "off",
46 | "@typescript-eslint/indent": "off",
47 | "multiline-ternary": "off",
48 | "react/jsx-closing-bracket-location": [
49 | 1,
50 | {
51 | "selfClosing": "tag-aligned",
52 | "nonEmpty": "after-props"
53 | }
54 | ]
55 | }
56 | }
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @dolfbarr
2 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | - push
5 | - pull_request
6 |
7 | jobs:
8 | build:
9 | name: Node.js ${{ matrix.node-version }}
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v2
14 | - uses: actions/setup-node@v2
15 | with:
16 | node-version: ${{ matrix.node-version }}
17 | - run: npm install
18 | - run: npm run lint
19 | - run: npm run type:check
20 | - run: npm run test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # MacOS
107 | .DS_store
108 |
109 | # VS code
110 | .vscode/
111 |
112 | # Parcel
113 | build/
114 | dist/
115 | .parcel-cache/
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npm run release:check
5 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v16
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "stories": [
3 | "../src/**/*.stories.mdx",
4 | "../src/**/*.stories.@(js|jsx|ts|tsx)"
5 | ],
6 | "addons": [
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials",
9 | "@storybook/addon-interactions"
10 | ],
11 | "framework": "@storybook/react"
12 | }
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | export const parameters = {
2 | actions: { argTypesRegex: "^on[A-Z].*" },
3 | controls: {
4 | matchers: {
5 | color: /(background|color)$/i,
6 | date: /Date$/,
7 | },
8 | },
9 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Dolf Barr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |

8 |

9 |

10 |

11 |

12 |

13 |
14 |
15 |
🪵 React Log Hook
16 |
Lightweight & customizable logging hook for your react components lifecycle
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 | # 🪵 react-log-hook
27 | React hook for logging per component lifecycle
28 |
29 | ## Features
30 | - 🪶 **Lightweight** — under *1.5 kB* gzipped & minified
31 | - 🗂️ **Typed** — made with TypeScript, shipped with types
32 | - 🥰 **Simple** — don't worry about any changes in your props & state
33 | - 🔧 **Customizable** — able to change everything you see in the logs
34 | - 🔬 **Tested** — up to 💯% unit test coverage
35 | - 🏎️ **Fast** — native react hooks & optimized
36 | - 📭 **No dependecies**
37 |
38 |
39 |
40 | ## Install
41 |
42 | With npm
43 |
44 | ```sh
45 | npm install -D react-log-hook
46 | ```
47 |
48 | With yarn
49 |
50 | ```sh
51 | yarn add -D react-log-hook
52 | ```
53 |
54 | ## Usage
55 |
56 | ### Basic usage
57 |
58 | ```javascript
59 | import { useLog } from 'react-log-hook'
60 |
61 | const App = () => {
62 | // Add a logger
63 | const { log } = useLog()
64 |
65 | const [state, setState] = useState(null)
66 |
67 | // Log the changes via console in real time!
68 | log(state)
69 |
70 | return null
71 | }
72 | ```
73 |
74 | ### Configuration options
75 |
76 | ```javascript
77 | import { useLog } from 'react-log-hook'
78 |
79 | const App = () => {
80 | // Any configuration properties are optional
81 | const { log } = useLog({
82 | environments: [
83 | /** Contains array of environments of `process.env.NODE_ENV` in which logging will be allowed */
84 | 'dev',
85 | 'development',
86 | ],
87 |
88 | // Print Options
89 |
90 | styles: {
91 | /** Contains styles object with different CSS inline styles used in logging */
92 | componentCSS:
93 | 'color: DodgerBlue' /** Inline css for rendering component name in the logs */,
94 | changeCSS:
95 | 'color: green; font-weight: bold;' /** Inline css for rendering current value in the logs */,
96 | subValueCSS:
97 | 'color: SlateGray; font-weight: thin;' /** Inline css for rendering any additional data like time or previous value in the logs */,
98 | },
99 | printer: console /** Contains custom implementation of console */,
100 | logLevel: 'log' /** Level of logging defined by console method */,
101 | /** Render object or array inline or via interactive browser renderer */
102 | inline: true,
103 | isGroupingEnabled: true /** Enable grouping for logs */,
104 | isGroupCollapsed: false /** Render groups collapsed */,
105 | groupLabelRenderer: (
106 | /** A function which will be used to render labels for the group */
107 | type /** Current stage of component lifecycle: 'Mount' | 'Change' | 'Unmount' */,
108 | componentName,
109 | ) => `${type}${componentName}`,
110 |
111 | // Custom Render Function
112 |
113 | render: function ({
114 | /** Custom function which will be used for rendering the result, provided with useful data */
115 | value,
116 | prevValue,
117 | type /** Current stage of component lifecycle: 'Mount' | 'Change' | 'Unmount' */,
118 | componentName,
119 | inline /** Render object or array inline or via interactive browser renderer */,
120 | flags: {
121 | isGrouped /** Enable grouping for logs */,
122 | isCollapsed /** Render groups collapsed */,
123 | },
124 | }) {
125 | console.log(value)
126 | },
127 | })
128 |
129 | const [state, setState] = useState(null)
130 |
131 | // It's possible to redefine any configuration option per log call!
132 | log(state, {
133 | inline: false,
134 | logLevel: 'warn',
135 | })
136 |
137 | return null
138 | }
139 | ```
140 |
141 | ## FAQ
142 |
143 | ### Will it deep copy the value to make sure it will persist in the logs?
144 |
145 | - 🎉 Yes, 🪵 **react-log-hook** deep copies the value to make sure it will not be changed in the logs later
146 |
147 | ### Do i need to install @types/react-log-hook as well?
148 |
149 | - 💪 No, 🪵 **react-log-hook** comes with prebundled types
150 |
151 | ### Will it run in production evironment?
152 |
153 | - ✅ By default 🪵 **react-log-hook** will run only in `dev` or `development` node evironments defined by `NODE_ENV`
154 |
155 | ## Roadmap
156 |
157 | - [x] Add previous state checking
158 | - [x] Use object copy to persist in time
159 | - [x] Use console groups to handle all the logs
160 | - [x] Add dev environment support by default
161 | - [x] Polish the looks with component names, function calls, time etc
162 | - [x] Add more customization options
163 | - [ ] Test with SSR & Server components
164 |
165 | ## Contributing
166 |
167 | - 🌟 Stars & 📥 Pull Requests are welcome for sure! ❤️
168 |
169 | ### Development
170 |
171 | 🪵 **react-log-hook** uses npm & npm scripts in development, the following scipts can be handy:
172 |
173 | #### `npm run start:demo`
174 | > Starts a demo app with enabled hook to check it in real environment
175 |
176 | #### `npm run storybook`
177 | > Starts storybook with example components to test against
178 |
179 | #### `npm run release:check`
180 | > Combination of linting, type-checking & tests; runs as precommit hook
181 |
182 | ## License
183 |
184 | [MIT License](LICENSE)
185 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Demo for React log hook
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { App } from '../src/index.stories'
4 |
5 | const container = document.getElementById('app')
6 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
7 | const root = createRoot(container!)
8 | root.render()
9 |
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * For a detailed explanation regarding each configuration property and type check, visit:
3 | * https://jestjs.io/docs/configuration
4 | */
5 |
6 | export default {
7 | // All imported modules in your tests should be mocked automatically
8 | // automock: false,
9 |
10 | // Stop running tests after `n` failures
11 | // bail: 0,
12 |
13 | // The directory where Jest should store its cached dependency information
14 | // cacheDirectory: "/private/var/folders/z1/z44tkmdd5wzc3_q3dpdg5l_80000gn/T/jest_dx",
15 |
16 | // Automatically clear mock calls, instances, contexts and results before every test
17 | clearMocks: true,
18 |
19 | // Indicates whether the coverage information should be collected while executing the test
20 | collectCoverage: true,
21 |
22 | // An array of glob patterns indicating a set of files for which coverage information should be collected
23 | // collectCoverageFrom: undefined,
24 |
25 | // The directory where Jest should output its coverage files
26 | coverageDirectory: 'coverage',
27 |
28 | // An array of regexp pattern strings used to skip coverage collection
29 | // coveragePathIgnorePatterns: [
30 | // "/node_modules/"
31 | // ],
32 |
33 | // Indicates which provider should be used to instrument code for coverage
34 | // coverageProvider: "babel",
35 |
36 | // A list of reporter names that Jest uses when writing coverage reports
37 | // coverageReporters: [
38 | // "json",
39 | // "text",
40 | // "lcov",
41 | // "clover"
42 | // ],
43 |
44 | // An object that configures minimum threshold enforcement for coverage results
45 | // coverageThreshold: undefined,
46 |
47 | // A path to a custom dependency extractor
48 | // dependencyExtractor: undefined,
49 |
50 | // Make calling deprecated APIs throw helpful error messages
51 | // errorOnDeprecated: false,
52 |
53 | // The default configuration for fake timers
54 | // fakeTimers: {
55 | // "enableGlobally": false
56 | // },
57 |
58 | // Force coverage collection from ignored files using an array of glob patterns
59 | // forceCoverageMatch: [],
60 |
61 | // A path to a module which exports an async function that is triggered once before all test suites
62 | // globalSetup: undefined,
63 |
64 | // A path to a module which exports an async function that is triggered once after all test suites
65 | // globalTeardown: undefined,
66 |
67 | // A set of global variables that need to be available in all test environments
68 | // globals: {},
69 |
70 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
71 | // maxWorkers: "50%",
72 |
73 | // An array of directory names to be searched recursively up from the requiring module's location
74 | // moduleDirectories: [
75 | // "node_modules"
76 | // ],
77 |
78 | // An array of file extensions your modules use
79 | // moduleFileExtensions: [
80 | // "js",
81 | // "mjs",
82 | // "cjs",
83 | // "jsx",
84 | // "ts",
85 | // "tsx",
86 | // "json",
87 | // "node"
88 | // ],
89 |
90 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
91 | // moduleNameMapper: {},
92 |
93 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
94 | // modulePathIgnorePatterns: [],
95 |
96 | // Activates notifications for test results
97 | // notify: false,
98 |
99 | // An enum that specifies notification mode. Requires { notify: true }
100 | // notifyMode: "failure-change",
101 |
102 | // A preset that is used as a base for Jest's configuration
103 | preset: 'ts-jest',
104 |
105 | // Run tests from one or more projects
106 | // projects: undefined,
107 |
108 | // Use this configuration option to add custom reporters to Jest
109 | // reporters: undefined,
110 |
111 | // Automatically reset mock state before every test
112 | // resetMocks: false,
113 |
114 | // Reset the module registry before running each individual test
115 | // resetModules: false,
116 |
117 | // A path to a custom resolver
118 | // resolver: undefined,
119 |
120 | // Automatically restore mock state and implementation before every test
121 | // restoreMocks: false,
122 |
123 | // The root directory that Jest should scan for tests and modules within
124 | // rootDir: undefined,
125 |
126 | // A list of paths to directories that Jest should use to search for files in
127 | // roots: [
128 | // ""
129 | // ],
130 |
131 | // Allows you to use a custom runner instead of Jest's default test runner
132 | // runner: "jest-runner",
133 |
134 | // The paths to modules that run some code to configure or set up the testing environment before each test
135 | // setupFiles: [],
136 |
137 | // A list of paths to modules that run some code to configure or set up the testing framework before each test
138 | // setupFilesAfterEnv: [],
139 |
140 | // The number of seconds after which a test is considered as slow and reported as such in the results.
141 | // slowTestThreshold: 5,
142 |
143 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing
144 | // snapshotSerializers: [],
145 |
146 | // The test environment that will be used for testing
147 | testEnvironment: 'jsdom',
148 |
149 | // Options that will be passed to the testEnvironment
150 | // testEnvironmentOptions: {},
151 |
152 | // Adds a location field to test results
153 | // testLocationInResults: false,
154 |
155 | // The glob patterns Jest uses to detect test files
156 | // testMatch: [
157 | // "**/__tests__/**/*.[jt]s?(x)",
158 | // "**/?(*.)+(spec|test).[tj]s?(x)"
159 | // ],
160 |
161 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
162 | // testPathIgnorePatterns: [
163 | // "/node_modules/"
164 | // ],
165 |
166 | // The regexp pattern or array of patterns that Jest uses to detect test files
167 | // testRegex: [],
168 |
169 | // This option allows the use of a custom results processor
170 | // testResultsProcessor: undefined,
171 |
172 | // This option allows use of a custom test runner
173 | // testRunner: "jest-circus/runner",
174 |
175 | // A map from regular expressions to paths to transformers
176 | // transform: undefined,
177 |
178 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
179 | // transformIgnorePatterns: [
180 | // "/node_modules/",
181 | // "\\.pnp\\.[^\\/]+$"
182 | // ],
183 |
184 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
185 | // unmockedModulePathPatterns: undefined,
186 |
187 | // Indicates whether each individual test should be reported during the run
188 | // verbose: undefined,
189 |
190 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
191 | // watchPathIgnorePatterns: [],
192 |
193 | // Whether to use watchman for file crawling
194 | // watchman: true,
195 | }
196 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-log-hook",
3 | "version": "1.2.2",
4 | "description": "React hook for logging per component lifecycle",
5 | "main": "dist/main.js",
6 | "module": "dist/module.js",
7 | "types": "dist/types.d.ts",
8 | "engines": {
9 | "node": ">= 12"
10 | },
11 | "scripts": {
12 | "start:demo": "parcel demo/index.html --dist-dir ./build",
13 | "build": "del-cli 'dist/*' && parcel build src/index.tsx --dist-dir ./dist && npm run size",
14 | "test": "jest",
15 | "lint": "eslint \"./**/*.ts\" --cache --cache-strategy content",
16 | "type:check": "tsc --noEmit true",
17 | "storybook": "start-storybook -p 6006",
18 | "build:storybook": "build-storybook",
19 | "release:check": "run-s lint type:check test",
20 | "release:test": "npm publish --dry-run",
21 | "release": "run-s release:check release:test build && np",
22 | "size": "size-limit",
23 | "prepare": "husky install"
24 | },
25 | "np": {
26 | "yarn": false,
27 | "testScript": "release:check"
28 | },
29 | "files": [
30 | "dist/*.{js,mjs,ts,map}",
31 | "LICENSE",
32 | "README.md",
33 | "package.json"
34 | ],
35 | "repository": {
36 | "type": "git",
37 | "url": "git+https://github.com/dolfbarr/react-log-hook.git"
38 | },
39 | "keywords": [
40 | "react",
41 | "parcel",
42 | "typescript",
43 | "hook",
44 | "react-hook",
45 | "log",
46 | "logging",
47 | "logger"
48 | ],
49 | "author": "Dolf Barr ",
50 | "license": "MIT",
51 | "bugs": {
52 | "url": "https://github.com/dolfbarr/react-log-hook/issues"
53 | },
54 | "homepage": "https://github.com/dolfbarr/react-log-hook#readme",
55 | "devDependencies": {
56 | "@babel/core": "^7.20.2",
57 | "@jest/globals": "^29.3.1",
58 | "@parcel/packager-ts": "^2.8.0",
59 | "@parcel/transformer-typescript-types": "^2.8.0",
60 | "@size-limit/preset-small-lib": "^8.1.0",
61 | "@storybook/addon-actions": "^6.5.13",
62 | "@storybook/addon-console": "^1.2.3",
63 | "@storybook/addon-essentials": "^6.5.13",
64 | "@storybook/addon-interactions": "^6.5.13",
65 | "@storybook/addon-links": "^6.5.13",
66 | "@storybook/builder-webpack4": "^6.5.13",
67 | "@storybook/manager-webpack4": "^6.5.13",
68 | "@storybook/react": "^7.4.6",
69 | "@storybook/testing-library": "^0.0.13",
70 | "@testing-library/react": "^13.4.0",
71 | "@types/jest": "^29.2.3",
72 | "@types/node": "^18.11.9",
73 | "@types/react": "^18.0.25",
74 | "@types/react-dom": "^18.0.9",
75 | "@typescript-eslint/eslint-plugin": "^5.44.0",
76 | "babel-loader": "^8.3.0",
77 | "del-cli": "^5.0.0",
78 | "eslint": "^8.28.0",
79 | "eslint-config-prettier": "^8.5.0",
80 | "eslint-config-standard-with-typescript": "^23.0.0",
81 | "eslint-plugin-import": "^2.26.0",
82 | "eslint-plugin-n": "^15.5.1",
83 | "eslint-plugin-prettier": "^4.2.1",
84 | "eslint-plugin-promise": "^6.1.1",
85 | "eslint-plugin-react": "^7.31.11",
86 | "husky": "^8.0.0",
87 | "jest": "^29.3.1",
88 | "jest-environment-jsdom": "^29.3.1",
89 | "np": "*",
90 | "npm-run-all": "^4.1.5",
91 | "parcel": "^2.8.0",
92 | "prettier": "^2.8.0",
93 | "process": "^0.11.10",
94 | "react": "^18.2.0",
95 | "react-dom": "^18.2.0",
96 | "size-limit": "^8.1.0",
97 | "ts-jest": "^29.0.3",
98 | "ts-node": "^10.9.1",
99 | "typescript": "^4.9.3"
100 | },
101 | "peerDependencies": {
102 | "react": "^16.8.x || 17.x || 18.x",
103 | "react-dom": "^16.8.x || 17.x || 18.x"
104 | },
105 | "size-limit": [
106 | {
107 | "path": "dist/main.js",
108 | "limit": "2 kB"
109 | },
110 | {
111 | "path": "dist/module.js",
112 | "limit": "2 kB"
113 | }
114 | ]
115 | }
116 |
--------------------------------------------------------------------------------
/react-log-hook-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dolfbarr/react-log-hook/2ac0551e54bd4d9728cfc6fdfffc94de06e07de0/react-log-hook-screenshot.png
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { LogLevels } from './types'
2 |
3 | export const CSS_COMPONENT = 'color: DodgerBlue'
4 | export const CSS_CHANGE = 'color: green; font-weight: bold;'
5 | export const CSS_SUB_VALUE = 'color: SlateGray; font-weight: thin;'
6 |
7 | export const ALLOWED_NODE_ENVS = ['dev', 'development']
8 |
9 | export const DEFAULT_LOG_LEVEL: LogLevels = 'log'
10 |
11 | export const DEFAULT_LABEL_SIZE = 14
12 |
13 | export const PREVIOUS_VALUE_LABEL = 'Previous Value'
14 | export const CURRENT_VALUE_LABEL = 'Current Value'
15 |
--------------------------------------------------------------------------------
/src/index.stories.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import { ComponentMeta } from '@storybook/react'
3 | import '@storybook/addon-console'
4 | import '@storybook/addon-actions/register'
5 | import { useLog } from '.'
6 |
7 | export function App(): React.ReactElement {
8 | const [isExampleMounted, setIsExampleMounted] = useState(true)
9 |
10 | setTimeout(function setIsMounted() {
11 | setIsExampleMounted(false)
12 | }, 3000)
13 |
14 | return (
15 |
16 |
Demo for React log hook.
17 |
Please check the console for logs.
18 | {isExampleMounted ?
: null}
19 |
20 | )
21 | }
22 |
23 | export function ExampleComponent(): React.ReactElement {
24 | const { log } = useLog()
25 | const [currentState, setCurrentState] = useState