epicweb-dev / react-hooks Goto Github PK
View Code? Open in Web Editor NEWLearn React Hooks! 🎣 ⚛
Home Page: https://react-hooks.epicweb.dev
License: Other
Learn React Hooks! 🎣 ⚛
Home Page: https://react-hooks.epicweb.dev
License: Other
This is just a suggestion in almost any exercise file. Instead of write the import like this:
import * as React from 'react';
it could be done like this, without the *
:
import React from 'react';
or even import hooks separately, like:
import { useState, useEffect } from 'react';
I don't know if this feedback is helpful or not. I mean it is just a subtle difference (and maybe just personal preference as well) I just find it more common in other React projects like this.
Hope this was helpful. :)
Would be nice to have the recent v18 updates on next
branch as well!
Here's what's going to be different in the next version of the react-hooks workshop (you can find all these changes in the next
branch until the videos are re-recorded):
./scripts/remove-ts
.key
you want now.I am getting error when installing dependencies. Here is the details.
npm WARN deprecated [email protected]: This loader has been deprecated. Please use eslint-webpack-plugin
npm WARN deprecated [email protected]: no longer actively maintained
npm WARN deprecated [email protected]: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated [email protected]: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
npm WARN deprecated @hapi/[email protected]: joi is leaving the @Hapi organization and moving back to 'joi' (hapijs/joi#2411)
npm WARN deprecated [email protected]: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-babel.
npm WARN deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated @hapi/[email protected]: This version has been deprecated and is no longer supported or maintained
npm WARN deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated [email protected]: request has been deprecated, see request/request#3142
npm WARN deprecated [email protected]: request-promise-native has been deprecated because it extends the now deprecated request package, see request/request#3142
npm WARN deprecated [email protected]: core-js@<3 is no longer maintained and not recommended for usage due
to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.
npm WARN deprecated [email protected]: this library is no longer supported
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm ERR! Unexpected end of JSON input while parsing near '...peerDependencies":{"@'
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\egil_\AppData\Roaming\npm-cache_logs\2020-10-03T21_47_00_491Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test: react-scripts test "--watchAll=false"
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Admin\AppData\Roaming\npm-cache_logs\2021-08-26T16_21_17_332Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test:coverage: npm run test -- --watchAll=false
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test:coverage script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Admin\AppData\Roaming\npm-cache_logs\2021-08-26T16_21_18_897Z-debug.log
ERROR: "test:coverage" exited with 1.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] validate: npm-run-all --parallel build test:coverage lint
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] validate script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Admin\AppData\Roaming\npm-cache_logs\2021-08-26T16_21_27_544Z-debug.log
Hey Kent! Thank you for the amazing course😁🚀
I was going through the React Hooks exercises and found these lines of code https://github.com/kentcdodds/react-hooks/blob/main/src/exercise/03.js#L38 and https://github.com/kentcdodds/react-hooks/blob/main/src/exercise/03.js#L33
Is there a reason to use template strings instead of espacing JSX directly to interpolate JS variables?
Thank you so much
If I open http://localhost:3000/isolated/examples/local-state-key-change.js
with a name already stored in local storage state from testing exercise 2, the page will not load and gives a few error messages.
Uncaught SyntaxError: Unexpected token 'e', "test" is not valid JSON
at parse (<anonymous>)
at utils.js:18:1
at mountState (react-dom.development.js:16986:1)
at Object.useState (react-dom.development.js:17699:1)
at Object.useState (react.development.js:1622:1)
at useLocalStorageState (utils.js:15:1)
at Greeting (local-state-key-change.js:10:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
The above error occurred in the <Greeting> component:
at Greeting (http://localhost:3000/static/js/src_examples_local-state-key-change_js.chunk.js:32:3)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
It works fine when I remove the name beforehand.
I am guessing this is due to the fact that I haven't completed the extra credit that turns the input name into JSON before storing it, but the useLocalStorageState in utils expects it to be in that format.
This is handled in 02.extra-4.js
with a try/catch that simply removes the offending item, but not in utils.js
, so it should be an easy fix :)
I have a question about the error handling extra credit in useEffect: HTTP requests. In the solution, the useEffect looks like this:
React.useEffect(() => { if (!pokemonName) { return } setPokemon(null) setError(null) fetchPokemon(pokemonName).then( pokemon => setPokemon(pokemon), error => setError(error), ) }, [pokemonName])
My question is, in the event of an error, how come we don't need to implement a .catch? I don't know if I am familiar with handling the error response in the .then.
I was doing the workshop over night and seemed to have nodded off 3 hours into it (around 430am). I am assuming the workshop was recorded and wondering if this is available somewhere online?
Hi Ken,
Very nice material, thanks.
Just to let you know about this API that you are using for this repo is no longer working:
"ZEIT Now 1.0 is being shut down. As part of this, all ZEIT Now 1.0 Deployments will become inaccessible."
Nothing to do with your code, but just in case I let you know.
The owner of the repo has been notified already: lucasbento/graphql-pokemon#13
Cheers!
For the main exercise in Lesson 6, there is this comment:
// 🐨 before calling `fetchPokemon`, make sure to update the loading state
However, as far as I can tell at this stage we don't have a loading state, and are just returning the <PokemonInfoFallback />
component if pokemon
is falsy and pokemonName
is truthy.
So I'm just wondering if I might open a PR to either clarify this comment or remove it entirely?
Thanks for the amazing course, Kent! I'm learning a bunch 😄
I am having a hard time with the code syntax highlight on the workshop apps for any of the topics including the react-hooks, an issue that I haven't had before.
my local specs:
I tried uninstalling and reinstalling several times no change. I have an idea what could have triggered it, I did a pull request on the repo after @kentcdodds updated the workshops to latest react 18 versions, not sure if anything happened then. Other than that no clue what could be causing an issue.
Hi Kent,
Congrats for such an amazing React course, epic I would say : -)
I just wanted to ask you abou the react hook flow example, and more specifically when I change the state on the App component, showChild state. Question is that the App re-renders and the Child component is mounted, but according to the output I'm getting I see that the App cleanup functions are running before the Child useEffect hooks.
This is what I'm getting:
And this is output show in the video:
Thank you very much in advance for your thoughts on this.
Jose
Hi Kent,
Working on this exercise, more particularly with the game history extra credit, I've seen that you use a couple of states: history and currentStep, so far so good.
Question is that when you click on any of the squares or you just restart the game, you are calling both setters: setHistory and setCurrentStep so this would trigger at least one re-render of the component. I assumed that React would re-render twice, but by consoling the component I've seen that only one re-render takes place so I was wondering how React manages this particular situation.
Thanks a lot in advance for your comments.
I'm looking through the README and in the Working Through It section it states:
You'll want to start in the intro/exercises directory where we start with raw React and DOM APIs. Pull open the .html files in your browser and follow along in the comments.
I can't seem to find this folder. Did my setup not work correctly?
Hi there 👋
In here https://epicreact.dev/modules/react-hooks/usestate-tic-tac-toe-extra-credit-solution-3 you used the index in the map loop as the key for each li
which I guess is considered a very bad and dangerous practice, could you tell us why did you go that way? I'm 100% sure that you are aware of that issue so thought might be something new in React that I'm not aware of.
We don’t recommend using indexes for keys if the order of items may change ...
https://reactjs.org/docs/lists-and-keys.html
Hello Kent!
src/__tests__/02.js
works fine with yours final src/final/02.extra-4.js
,
yet when just copying to src/exercise/02.js
, same contents,
updating test to take
import App from '../exercise/02'
it fails with on line 14
screen.getByText(/hello.*jill/i)
Thanks!
Avraham
In https://github.com/kentcdodds/react-hooks/blob/main/src/exercise/06.md, it says "This ensures that you don't return anything but a cleanup function", but the example above it does not return a cleanup function. This might be confusing to a beginner who might think that the async function is a cleanup function, or that "effect()" is somehow being magically returned. I feel that the sentence could've been avoided altogether, or phrased as "This ensures that you don't return anything (unless you explicitly return a cleanup function)" - or something along those lines.
For this extra credit, using resetKeys={[pokemonName]}
is effectively the same as using key={pokemonName}
, because it ends up mounting the <PokemonInfo />
component from scratch. This means the UI still flashes up the idle
state.
One way to fix the problem of the flashing idle
state is to check the pokemonName
when setting the initial status
property on the state object. I can see this has been done in the final exercise files for both extra credit 7 and extra credit 8.
Suggestions:
status: pokemonName ? 'pending' : 'idle'
for extra credit 7, because it doesn't naturally fit with the flow of what is being asked for. (unless I've misread something)resetKeys=[pokemonName]
acts similarly to key={pokemonName}
and prompt them to think how else the <PokemonInfo />
can be changed so that the status
doesn't always start as idle
.Happy to raise a PR if you agree.
Above code needs to be changed to below code (same goes for all the other 02 extra credit solution files):
window.localStorage.getItem('name') ?? initialName,
This is because the current code causes a bug. The bug is basically not properly accounting for the edge-case where .getItem()
can return an empty string. So then the input element will show incorrect text. (When this bug happens and how it looks will be clear when you follow the below steps to reproduce.)
Steps to reproduce the bug:
initialName
prop set to foo
."foo"
. Delete all text in input so that it's blank.""
to be loaded from local storage instead of "foo"
. After all, that is the last value you set for the input. The component should remember that and treat the empty string no differently than any other string. "foo"
should only be shown if there is no value with key name
in local storage. But instead, you'll see that the result is that the input shows the "foo"
text.You might also want to create a test to check for this bug, since the 02 exercise tests don't catch this bug. And the bug is really easy for your students to make and not notice, so it'd be useful to do I think.
i wouldn't expect it to be a huge problem it's cool thing that it might need small updated(or notification) so people can learn about state batching and how it works since React 18 rolled the case where state batching also work on async operations
i think this is no longer an issue as i'v tried it on my actual workspace and it worked fine , or i might be the one missing something ?
Thank your for the effort creating such beautiful and well made course ,
I'm working on exercise 6 with error boundary and even though my code is exactly the same as yours, it doesn't work. I still see a crashing error.
I did a little research and seems like ErrorBoundary only works in production mode. In development mode, the red screen will still be shown for easier debugging.
If this is correct then I think it would be great if you can adjust the code template for exercise 6 or adding some notes there.
@kentcdodds
Hi Kent,I am Aimee.And I am a junior developer.
I've recently encountered some problems in learning react, and I hope I can get some help from you.
if a state of component has updated with the same value, I expect React will not actually rerender the component due to the optimation logic. In the demo below, component rerendered when state value change from 1 to 2, that's what I expected. However, changing the value of state from 2 to 2 will also cause component rendered.
Why does it cause the second rendering?That's I want to ask you.Looking forward to your reply.Thank you.
https://codesandbox.io/s/sweet-maxwell-29o28?file=/src/App.js
#90
For some reasons when reset function is invoked only the 'squares' state gets updated but others remain as is. Expected behavior would be all states get updated as a result of the 'squares' state update
It seems there is some interference with NextJS and this repo that is causing endless rerenders in the second course 02.js.
Luckily I have an open source NextJS repo to share on which the bug is occuring when playing together with this repo.
Reproduction:
src/exercise/02.js
yarn && yarn dev
, it should open a server on localhost:3000, wait to load the start pageThis is verified in Chrome 87.0.4280.141, I did not check other browsers. Here's a video of the bug: https://drive.google.com/file/d/1TQKuMjDM1CPDENWiSg8uI4l3JRPpovvz/view
Hi, I just run node setup on my system(MacOS Ventura), which has Node.js 20 installed. It gives me an error and recommends that I use Node.js 18 or below. Even more confusing is that it recommends that I update to the latest version of Node. But am already using the latest version:
stanley@MACOOKs-MBP react-hooks % node setup
▶️ Starting workshop setup...
Running the following command: npx "https://gist.github.com/kentcdodds/bb452ffe53a5caa3600197e1d8005733" -q
▶️ Starting: System Validation
Ensuring the correct versions of tools are installed on this computer.
Running the following command: npx "https://gist.github.com/kentcdodds/abbc32701f78fa70298d444c2303b6d9"
There were errors validating the compatibility of this computer:
This computer has [email protected] installed, but node@14 || 16 || 18 is required. Please update node: https://nodejs.org
If you would like to just ignore this error, then feel free to do so and install dependencies as you normally would in "/Users/stanley/react-hooks". Just know that things may not work properly if you do...
🚨 Failure: System Validation. Please review the messages above for information on how to troubleshoot and resolve this issue.
Hi,
On a fresh clone, and after running node setup
and npm start
. I get an error when trying to open the exercise on a browser, using my network IP.
npm start
npm start
outputs thisCompiled successfully!
You can now view react-hooks in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.1.222:3000
Note that the development build is not optimized.
To create a production build, use npm run build.
http://192.168.1.222:3000
on your browserThe iframe will show the following error:
Unhandled Rejection (Error): [MSW] Failed to register a Service Worker: this browser does not support Service Workers (see https://caniuse.com/serviceworkers), or your application is running on an insecure host (consider using HTTPS for custom hostnames).
▶ 10 stack frames were collapsed.
__webpack_require__
src/epicreact/react-hooks/webpack/bootstrap:856
853 |
854 | __webpack_require__.$Refresh$.init();
855 | try {
> 856 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 857 | } finally {
858 | __webpack_require__.$Refresh$.cleanup(moduleId);
859 | }
View compiled
fn
src/epicreact/react-hooks/webpack/bootstrap:150
147 | );
148 | hotCurrentParents = [];
149 | }
> 150 | return __webpack_require__(request);
| ^ 151 | };
152 | var ObjectFactory = function ObjectFactory(name) {
153 | return {
View compiled
1
http://192.168.1.222:3000/static/js/main.chunk.js:1054:18
__webpack_require__
src/epicreact/react-hooks/webpack/bootstrap:856
853 |
854 | __webpack_require__.$Refresh$.init();
855 | try {
> 856 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 857 | } finally {
858 | __webpack_require__.$Refresh$.cleanup(moduleId);
859 | }
View compiled
checkDeferredModules
src/epicreact/react-hooks/webpack/bootstrap:45
42 | }
43 | if(fulfilled) {
44 | deferredModules.splice(i--, 1);
> 45 | result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
| ^ 46 | }
47 | }
48 |
View compiled
Array.webpackJsonpCallback [as push]
src/epicreact/react-hooks/webpack/bootstrap:32
29 | deferredModules.push.apply(deferredModules, executeModules || []);
30 |
31 | // run deferred modules when all chunks ready
> 32 | return checkDeferredModules();
| ^ 33 | };
34 | function checkDeferredModules() {
35 | var result;
View compiled
(anonymous function)
http://192.168.1.222:3000/static/js/main.chunk.js:1:75
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error. Click the 'X' or hit ESC to dismiss this message.
the error output is the following
▶️ Starting workshop setup...
Running the following command: npx "https://gist.github.com/kentcdodds/bb452ffe53a5caa3600197e1d8005733" -q
npm ERR! code 1
npm ERR! Command failed: git submodule update -q --init --recursive
npm ERR! C:/Program Files/Git/mingw64/libexec/git-core\git-submodule: line 22: .: git-sh-setup: file not found
npm ERR!
Even tho i tried to do an npm install
to fix the issue it shows a different type of error and that's very weird
npm ERR! cb() never called!
npm ERR! This is an error with npm itself. Please report this error at:
npm ERR! **<https://npm.community>**
Location: src/exercise/02.js
On line 25, you are missing the value={name}
in the input element.
Node v14.15.4
Starting the development server...
<--- Last few GCs --->
[57556:0x150008000] 1117 ms: Scavenge 68.7 (97.6) -> 59.3 (97.6) MB, 2.7 / 0.0 ms (average mu = 0.985, current mu = 0.985) allocation failure
[57556:0x150008000] 1211 ms: Scavenge 73.7 (97.8) -> 61.5 (97.8) MB, 1.5 / 0.0 ms (average mu = 0.985, current mu = 0.985) allocation failure
<--- JS stacktrace --->
FATAL ERROR: wasm code commit Allocation failed - process out of memory
1: 0x104b229d8 node::Abort() [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
2: 0x104b22b58 node::errors::TryCatchScope::~TryCatchScope() [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
3: 0x104c3c384 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
4: 0x104c3c318 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
5: 0x1051d1cdc v8::internal::wasm::WasmCodeAllocator::AllocateForCodeInRegion(v8::internal::wasm::NativeModule*, unsigned long, v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
6: 0x1051d2970 v8::internal::wasm::NativeModule::CreateEmptyJumpTableInRegion(int, v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
7: 0x1051d1638 v8::internal::wasm::NativeModule::AddCodeSpace(v8::base::AddressRegion, v8::internal::wasm::WasmCodeAllocator::OptionalLock const&) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
8: 0x1051d2780 v8::internal::wasm::NativeModule::NativeModule(v8::internal::wasm::WasmEngine*, v8::internal::wasm::WasmFeatures const&, v8::internal::VirtualMemory, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, std::__1::shared_ptr<v8::internal::Counters>, std::__1::shared_ptr<v8::internal::wasm::NativeModule>*) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
9: 0x1051d4cf4 v8::internal::wasm::WasmCodeManager::NewNativeModule(v8::internal::wasm::WasmEngine*, v8::internal::Isolate*, v8::internal::wasm::WasmFeatures const&, unsigned long, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
10: 0x1051e0808 v8::internal::wasm::WasmEngine::NewNativeModule(v8::internal::Isolate*, v8::internal::wasm::WasmFeatures const&, std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
11: 0x1051afb54 v8::internal::wasm::AsyncCompileJob::CreateNativeModule(std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
12: 0x1051afd1c v8::internal::wasm::AsyncCompileJob::GetOrCreateNativeModule(std::__1::shared_ptr<v8::internal::wasm::WasmModule const>, unsigned long) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
13: 0x1051b8380 v8::internal::wasm::AsyncCompileJob::PrepareAndStartCompile::RunInForeground(v8::internal::wasm::AsyncCompileJob*) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
14: 0x1051b814c v8::internal::wasm::AsyncCompileJob::CompileTask::RunInternal() [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
15: 0x104b7fc08 node::PerIsolatePlatformData::RunForegroundTask(std::__1::unique_ptr<v8::Task, std::__1::default_delete<v8::Task> >) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
16: 0x104b7e8a0 node::PerIsolatePlatformData::FlushForegroundTasksInternal() [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
17: 0x105335c20 uv__async_io [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
18: 0x1053477e0 uv__io_poll [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
19: 0x1053360b0 uv_run [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
20: 0x104b5af40 node::NodeMainInstance::Run() [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
21: 0x104afb7d0 node::Start(int, char**) [/Users/dguryev/.nvm/versions/node/v14.15.4/bin/node]
22: 0x181464f34 start [/usr/lib/system/libdyld.dylib]
Hi, I'm wondering what does useRef
do in this case.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.