diff --git a/doczrc.js b/doczrc.js index 253ab08..0f184f3 100644 --- a/doczrc.js +++ b/doczrc.js @@ -13,6 +13,7 @@ export default { 'useCallback', 'useMemo', 'useRef', + 'useDebugValue', 'Examples' ], wrapper: 'src/docs/config/Wrapper.js', diff --git a/src/components/Editor.js b/src/components/Editor.js index 70a82e1..2b6c825 100644 --- a/src/components/Editor.js +++ b/src/components/Editor.js @@ -1,13 +1,14 @@ import React, { - useState, - useEffect, - useLayoutEffect, - useCallback, - useContext, - useMemo, - useReducer, - useRef, - memo + useState, + useEffect, + useLayoutEffect, + useCallback, + useContext, + useMemo, + useReducer, + useRef, + useDebugValue, + memo, } from 'react' import styled, { css } from 'styled-components' import * as polished from 'polished' @@ -15,94 +16,111 @@ import { foreground, red, lightGrey } from '../utils/colors' import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live' +function useCount(initialValue) { + const [count, setCount] = useState(initialValue) + useDebugValue(count) + const increment = () => setCount(c => c + 1) + const decrement = () => setCount(c => c - 1) + return [count, increment, decrement] +} + +function useDate() { + const [date] = useState(new Date()) + useDebugValue(date, date => date.toISOString()) + return date +} + const StyledProvider = styled.div` - border-radius: ${polished.rem(3)}; - box-shadow: 1px 1px 20px rgba(20, 20, 20, 0.27); - overflow: hidden; - margin-bottom: ${polished.rem(100)}; + border-radius: ${polished.rem(3)}; + box-shadow: 1px 1px 20px rgba(20, 20, 20, 0.27); + overflow: hidden; + margin-bottom: ${polished.rem(100)}; ` const LiveWrapper = styled.div` - display: flex; - flex-direction: row; - justify-content: stretch; - align-items: stretch; - @media (max-width: 600px) { - flex-direction: column; - } + display: flex; + flex-direction: row; + justify-content: stretch; + align-items: stretch; + @media (max-width: 600px) { + flex-direction: column; + } ` const column = css` - flex-basis: 50%; - width: 50%; - max-width: 50%; - @media (max-width: 600px) { - flex-basis: auto; - width: 100%; - max-width: 100%; - } + flex-basis: 50%; + width: 50%; + max-width: 50%; + @media (max-width: 600px) { + flex-basis: auto; + width: 100%; + max-width: 100%; + } ` const StyledEditor = styled.div` - background: ${lightGrey}; - font-family: 'Source Code Pro', monospace; - font-size: ${polished.rem(14)}; - height: ${props => (props.autoEditorHeight ? 'auto' : polished.rem(350))}; - max-height: auto; - overflow: auto; - ${column}; - * > textarea:focus { - outline: none; - } + background: ${lightGrey}; + font-family: 'Source Code Pro', monospace; + font-size: ${polished.rem(14)}; + height: ${props => (props.autoEditorHeight ? 'auto' : polished.rem(350))}; + max-height: auto; + overflow: auto; + ${column}; + * > textarea:focus { + outline: none; + } ` const StyledPreview = styled.div` - position: relative; - padding: 0.5rem; - background: white; - color: black; - height: auto; - overflow: hidden; - ${column}; + position: relative; + padding: 0.5rem; + background: white; + color: black; + height: auto; + overflow: hidden; + ${column}; ` const StyledError = styled(LiveError)` - display: block; - padding: ${polished.rem(8)}; - background: ${red}; - color: ${foreground}; - white-space: pre-wrap; - text-align: left; - font-size: 0.9em; - font-family: 'Source Code Pro', monospace; + display: block; + padding: ${polished.rem(8)}; + background: ${red}; + color: ${foreground}; + white-space: pre-wrap; + text-align: left; + font-size: 0.9em; + font-family: 'Source Code Pro', monospace; ` const defaultScope = { - useState, - useEffect, - useLayoutEffect, - useMemo, - useReducer, - useRef, - useCallback, - useContext, - memo + useState, + useEffect, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useCallback, + useContext, + useDebugValue, + useCount, + useDate, + memo, } const Editor = ({ noInline, code, autoEditorHeight }) => ( - - - - - - - - - - - - - + + + + + + + + + + + + + ) export default Editor diff --git a/src/components/examples/useDebugValue.js b/src/components/examples/useDebugValue.js new file mode 100644 index 0000000..229dc56 --- /dev/null +++ b/src/components/examples/useDebugValue.js @@ -0,0 +1,28 @@ +export const useDebugValueCode = `() => { + const [count, setCount] = useState(0) + const [date, setDate] = useState(new Date()) + + const increment = () => { + setCount(c => c + 1) + setDate(new Date()) + useDebugValue({count, date}) + } + const decrement = () => { + setCount(c => c - 1) + setDate(new Date()) + useDebugValue({count, date}) + } + + return ( +
+
+

Count: {count}

+ + +

Date: {date.toISOString()}

+

Open React DevTools to see the debug values for the custom hooks.

+
+
+ ); +} +` diff --git a/src/docs/useDebugValue.mdx b/src/docs/useDebugValue.mdx new file mode 100644 index 0000000..6d47c9e --- /dev/null +++ b/src/docs/useDebugValue.mdx @@ -0,0 +1,44 @@ +--- +name: useDebugValue +route: /useDebugValue +--- + +import Editor from '../components/Editor' +import { useDebugValueCode } from '../components/examples/useDebugValue'; + +# useDebugValue + +`useDebugValue` is a React Hook that lets you add a label to a custom hook in React DevTools. + +## Reference + +### `useDebugValue(value, format?)` + +Call `useDebugValue` at the top level of your [custom Hook](https://react.dev/learn/reusing-logic-with-custom-hooks) to display a readable debug value for React DevTools. + +#### Parameters + +* `value`: The value you want to display in React DevTools. It can be of any type. +* `format?`: An optional formatting function. When DevTools needs to display the value, it will call this function and display the formatted result. This lets you do expensive formatting only when the hook is inspected. + +#### Returns + +`useDebugValue` does not return anything. + +## Usage + +### Adding a label to a custom Hook + +Call `useDebugValue` in a custom Hook to display a readable debug value for React DevTools. + + + +In this example: + +1. We define a component that manages a count and a date state using `useState`. +2. The component has two functions, `increment` and `decrement`, which update both the count and date states. +3. Inside these functions, we use `useDebugValue` to display the current count and date values in React DevTools. +4. The component renders a simple interface with the current count, buttons to increment and decrement, and the current date. +5. When you inspect this component in React DevTools, you'll see the debug value containing the current count and date for each state update. + +This example demonstrates how `useDebugValue` can provide real-time information about the internal state of a component, making it easier to track state changes and debug your application's behavior. It's particularly useful when you want to monitor multiple pieces of state simultaneously. \ No newline at end of file