diff --git a/.travis.yml b/.travis.yml index ad4d6e410..c19d800e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ node_js: - lts/* script: - npm run extractor -- npm run builder after_success: - chmod +x .travis/push.sh -- .travis/push.sh \ No newline at end of file +- .travis/push.sh diff --git a/.travis/push.sh b/.travis/push.sh index f60647fd8..b3546d61f 100644 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -25,7 +25,7 @@ upload_files() { if [ $TRAVIS_EVENT_TYPE != "pull_request" ]; then if [ $TRAVIS_BRANCH == "master" ]; then echo "Pushing to master branch..." - git push --force --quiet "https://${GH_TOKEN}@github.com/30-seconds/30-seconds-of-react.git" master > /dev/null 2>&1 + git push --quiet "https://${GH_TOKEN}@github.com/30-seconds/30-seconds-of-react.git" master > /dev/null 2>&1 fi fi } diff --git a/README.md b/README.md index 674d9e04f..369616e24 100644 --- a/README.md +++ b/README.md @@ -1,2506 +1,26 @@ - +[](https://30secondsofcode.org/react/p/1) # 30 seconds of React -> Curated collection of useful React snippets that you can understand in 30 seconds or less. +> Short React code snippets for all your development needs -- Use Ctrl + F or command + F to search for a snippet. -- Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). -- Snippets are written in React 16.8+, using hooks. +* Visit [our website](https://30secondsofcode.org) to view our snippet collection. +* Use the [Search page](https://30secondsofcode.org/search) to find snippets that suit your needs. You can search by name, tag, language or using a snippet's description. Just start typing a term and see what comes up. +* Browse the [React Snippet List](https://30secondsofcode.org/react/p/1) to see all the snippets in this project or click individual tags at the top of the same page to narrow down your search to a specific tag. +* Click on each snippet card to view the whole snippet, including code, explanation and examples. +* You can use the button on the right side of a snippet card to copy the code to clipboard. +* If you like the project, give it a star. It means a lot to the people maintaining it. -### Prerequisites +## Want to contribute? -To import a snippet into your project, you must import `React` and copy-paste the component's JavaScript code like this: +* If you want to help us improve, take a minute to read the [Contribution Guidelines](/CONTRIBUTING.md) first. +* Use the [Snippet Template](/snippet-template.md) to add new snippets to the collection. +* If you find a problem with a specific snippet, please [open an issue](https://github.com/30-seconds/30-seconds-of-react/issues/new). +* If you find a problem with the website, please [report it in the web repository](https://github.com/30-seconds/30-seconds-web/issues/new). -```js -import React from 'react'; - -function MyComponent(props) { - /* ... */ -} -``` - -If there is any CSS related to your component, copy-paste it to a new file with the same name and the appropriate extension, then import it like this: - -```js -import './MyComponent.css'; -``` - -To render your component, make sure there is a node with and id of `"root"` present in your element (preferrably a `
| ID | -Value | -
|---|---|
| {i} | -{val} | -
| ` element. -- Use `Array.prototype.map` to render each object in the `filteredData` array as a ` | ||
|---|---|---|
` for each key in the object.
-
-_This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`_
-
-```jsx
-function MappedTable({ data, propertyNames }) {
- let filteredData = data.map(v =>
- Object.keys(v)
- .filter(k => propertyNames.includes(k))
- .reduce((acc, key) => ((acc[key] = v[key]), acc), {})
- );
- return (
-
-
-
-Examples- -```jsx -const people = [ - { name: 'John', surname: 'Smith', age: 42 }, - { name: 'Adam', surname: 'Smith', gender: 'male' } -]; -const propertyNames = ['name', 'surname', 'age']; -ReactDOM.render( -[⬆ Back to top](#contents) - ---- - -## Hooks - - -### useClickInside - -A hook that handles the event of clicking inside the wrapped component. - -- Create a custom hook that takes a `ref` and a `callback` to handle the `click` event. -- Use the `React.useEffect()` hook to append and clean up the `click` event. -- Use the `React.useRef()` hook to create a `ref` for your click component and pass it to the `useClickInside` hook. - -```jsx -const useClickInside = (ref, callback) => { - const handleClick = e => { - if (ref.current && ref.current.contains(e.target)) { - callback(); - } - }; - React.useEffect(() => { - document.addEventListener('click', handleClick); - return () => { - document.removeEventListener('click', handleClick); - }; - }); -}; -``` - -
-
-
-Examples- -```jsx -const ClickBox = ({ onClickInside }) => { - const clickRef = React.useRef(); - useClickInside(clickRef, onClickInside); - return ( -
-
- );
-};
-
-ReactDOM.render(
- Click inside this element -[⬆ Back to top](#contents) - -### useClickOutside - -A hook that handles the event of clicking outside of the wrapped component. - -- Create a custom hook that takes a `ref` and a `callback` to handle the `click` event. -- Use the `React.useEffect()` hook to append and clean up the `click` event. -- Use the `React.useRef()` hook to create a `ref` for your click component and pass it to the `useClickOutside` hook. - -```jsx -const useClickOutside = (ref, callback) => { - const handleClick = e => { - if (ref.current && !ref.current.contains(e.target)) { - callback(); - } - }; - React.useEffect(() => { - document.addEventListener('click', handleClick); - return () => { - document.removeEventListener('click', handleClick); - }; - }); -}; -``` - -
-
-
-Examples- -```jsx -const ClickBox = ({ onClickOutside }) => { - const clickRef = React.useRef(); - useClickOutside(clickRef, onClickOutside); - return ( -
-
- );
-};
-
-ReactDOM.render(
- Click out of this element -[⬆ Back to top](#contents) - -### useFetch - -A hook that implements `fetch` in a declarative manner. - -- Create a custom hook that takes a `url` and `options`. -- Use the `React.useState()` hook to initialize the `response` and `error` state variables. -- Use the `React.useEffect()` hook to anychronously call `fetch()` and update the state varaibles accordingly. -- Return an object containting the `response` and `error` state variables. - -```jsx -const useFetch = (url, options) => { - const [response, setResponse] = React.useState(null); - const [error, setError] = React.useState(null); - - React.useEffect(() => { - const fetchData = async () => { - try { - const res = await fetch(url, options); - const json = await res.json(); - setResponse(json); - } catch (error) { - setError(error); - } - }; - fetchData(); - }, []); - - return { response, error }; -}; -``` - -
-
-
-Examples- -```jsx -const ImageFetch = props => { - const res = useFetch('https://dog.ceo/api/breeds/image/random', {}); - if (!res.response) { - returnLoading... ;
- }
- const imageUrl = res.response.message;
- return (
-
-
- );
-};
-
-ReactDOM.render([⬆ Back to top](#contents) - -### useInterval - -A hook that implements `setInterval` in a declarative manner. - -- Create a custom hook that takes a `callback` and a `delay`. -- Use the `React.useRef()` hook to create a `ref` for the callback function. -- Use the `React.useEffect()` hook to remember the latest callback. -- Use the `React.useEffect()` hook to set up the interval and clean up. - -```jsx -const useInterval = (callback, delay) => { - const savedCallback = React.useRef(); - - React.useEffect(() => { - savedCallback.current = callback; - }, [callback]); - - React.useEffect(() => { - function tick() { - savedCallback.current(); - } - if (delay !== null) { - let id = setInterval(tick, delay); - return () => clearInterval(id); - } - }, [delay]); -}; -``` - -
-
-
-Examples- -```jsx -const Timer = props => { - const [seconds, setSeconds] = React.useState(0); - useInterval(() => { - setSeconds(seconds + 1); - }, 1000); - - return{seconds} ; -}; - -ReactDOM.render([⬆ Back to top](#contents) - -### useNavigatorOnLine - -A hook that returns if the client is online or offline. - -- Create a function, `getOnLineStatus`, that uses the `NavigatorOnLine` web API to get the online status of the client. -- Use the `React.useState()` hook to create an appropriate state variable, `status`, and setter. -- Use the `React.useEffect()` hook to add listeners for appropriate events, updating state, and cleanup those listeners when unmounting. -- Finally return the `status` state variable. - -```jsx -const getOnLineStatus = () => - typeof navigator !== "undefined" && typeof navigator.onLine === "boolean" - ? navigator.onLine - : true; - -const useNavigatorOnLine = () => { - const [status, setStatus] = React.useState(getOnLineStatus()); - - const setOnline = () => setStatus(true); - const setOffline = () => setStatus(false); - - React.useEffect(() => { - window.addEventListener("online", setOnline); - window.addEventListener("offline", setOffline); - - return () => { - window.removeEventListener("online", setOnline); - window.removeEventListener("offline", setOffline); - }; - }, []); - - return status; -}; -``` - -
-
-
-Examples- -```jsx -const StatusIndicator = () => { - const isOnline = useNavigatorOnLine(); - - return You are {isOnline ? "online" : "offline"}.; -}; - -ReactDOM.render([⬆ Back to top](#contents) - -### useSSR - -A hook that checks if the code is running on the browser or the server. - -- Create a custom hook that returns an appropriate object. -- Use `typeof window`, `window.document` and `window.document.createElement` to check if the code is running on the browser. -- Use the `React.useState()` hook to define the `inBrowser` state variable. -- Use the `React.useEffect()` hook to update the `inBrowser` state variable and clean up at the end. -- Use the `React.useMemo()` to memoize the return values of the custom hook. - -```jsx -const isDOMavailable = !!( - typeof window !== 'undefined' && - window.document && - window.document.createElement -); - -const useSSR = (callback, delay) => { - const [inBrowser, setInBrowser] = React.useState(isDOMavailable); - - React.useEffect(() => { - setInBrowser(isDOMavailable); - return () => { - setInBrowser(false); - } - }, []); - - const useSSRObject = React.useMemo(() => ({ - isBrowser: inBrowser, - isServer: !inBrowser, - canUseWorkers: typeof Worker !== 'undefined', - canUseEventListeners: inBrowser && !!window.addEventListener, - canUseViewport: inBrowser && !!window.screen - }), [inBrowser]); - - return React.useMemo(() => Object.assign(Object.values(useSSRObject), useSSRObject), [inBrowser]); -}; -``` - -
-
-
-Examples- -```jsx -const SSRChecker = props => { - let { isBrowser, isServer } = useSSR(); - - return{ isBrowser ? 'Running on browser' : 'Running on server' } ; -}; - -ReactDOM.render([⬆ Back to top](#contents) - -### useTimeout - -A hook that implements `setTimeout` in a declarative manner. - -- Create a custom hook that takes a `callback` and a `delay`. -- Use the `React.useRef()` hook to create a `ref` for the callback function. -- Use the `React.useEffect()` hook to remember the latest callback. -- Use the `React.useEffect()` hook to set up the timeout and clean up. - -```jsx -const useTimeout = (callback, delay) => { - const savedCallback = React.useRef(); - - React.useEffect(() => { - savedCallback.current = callback; - }, [callback]); - - React.useEffect(() => { - function tick() { - savedCallback.current(); - } - if (delay !== null) { - let id = setTimeout(tick, delay); - return () => clearTimeout(id); - } - }, [delay]); -}; -``` - -
-
-
-Examples- -```jsx -const OneSecondTimer = props => { - const [seconds, setSeconds] = React.useState(0); - useTimeout(() => { - setSeconds(seconds + 1); - }, 1000); - - return{seconds} ; -}; - -ReactDOM.render([⬆ Back to top](#contents) - ---- - -## Input - - -### ControlledInput - -Renders an `` element with internal state, that uses a callback function to pass its value to the parent component. - -- Use object destructuring to set defaults for certain attributes of the `` element. -- Use the `React.setState()` hook to create the `value` state variable and give it a value of equal to the `defaultValue` prop. -- Use the `React.useEffect()` hook with a second parameter set to the `value` state variable to call the `callback` function every time `value` is updated. -- Render an `` element with the appropriate attributes and use the the `onChange` event to upda the `value` state variable. - -```jsx -function ControlledInput({ - callback, - type = 'text', - disabled = false, - readOnly = false, - defaultValue, - placeholder = '' -}) { - const [value, setValue] = React.useState(defaultValue); - - React.useEffect(() => { - callback(value); - }, [value]); - - return ( - setValue(value)} - /> - ); -} -``` - -
-
-
-Examples- -```jsx -ReactDOM.render( -[⬆ Back to top](#contents) - -### LimitedTextarea - -Renders a textarea component with a character limit. - -- Use the `React.useState()` hook to create the `content` state variable and set its value to `value`. - Create a method `setFormattedContent`, which trims the content of the input if it's longer than `limit`. -- Use the `React.useEffect()` hook to call the `setFormattedContent` method on the value of the `content` state variable. -- Use a` ` to wrap both the` |