epicweb-dev / advanced-react-patterns Goto Github PK
View Code? Open in Web Editor NEWThis is the latest advanced react patterns workshop
Home Page: https://advanced-react-patterns.epicweb.dev
License: Other
This is the latest advanced react patterns workshop
Home Page: https://advanced-react-patterns.epicweb.dev
License: Other
Is this the official site for this repo or is it an infringement? I'm signed up for Epic React and the content looks extremely similar but the name seems to come from here.
I'm looking for a good place to link the Prop Getter pattern and I don't want to peddle in imposters.
As discussed on https://discord.com/channels/715220730605731931/759594637496811520/871062940487417866, it would be nice to have a 1-liner summary on top of each pattern, even before the Background, to make it easier for us to re-visit the patterns and trigger our memory.
Although the Readme states that node 17 should be working, the node setup
command fails for me with the following message:
▶️ 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@12 || 14 || 15 || 16 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/roda/Documents/Development/advanced-react-patterns". 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.
In excerise 03 the Toggle component takes children
function Toggle({children}) {
const [on, setOn] = React.useState(false)
const toggle = () => setOn(!on)
return (
<ToggleContext.Provider value={{on, toggle}}>
{children}
</ToggleContext.Provider>
)
}
but what if it took default children
function Toggle({ children }) {
const [on, setOn] = React.useState(false);
const toggle = () => setOn(!on);
return (
<ToggleContext.Provider value={{ on, toggle }}>
{children || (
<>
<ToggleOn>The button is on</ToggleOn>
<ToggleOff>The button is off</ToggleOff>
<ToggleButton />
</>
)}
</ToggleContext.Provider>
);
}
and now you can use it like this
<div>
{/* default children */}
<Toggle />
{/* OR */}
{/* explicit children */}
<Toggle>
<ToggleOn>This button is on</ToggleOn>
<ToggleOff>This button is off</ToggleOff>
<ToggleButton />
</Toggle>
</div>
what are your opinion on giving default children? could this lead to any problems?
There's no config/tsconfig.exercise.json
file, even though the Readme is suggesting editing it.
I'm preparing for today's workshop, and the readme here in the "TypeScript" part suggests that, to enable the TS Strict mode, one should configure it in config/tsconfig.exercise.json
file. However, there is no such file, nor config/
directory. I am not certain if it's worth the effort, but I think either rewording this ("create config/tsconfig...") or creating a placeholder tsconfig file there should help with first-time setup of the repo.
I'm seeing the following error after running npm start
: Element type is invalid. Received a promise that resolves to: /static/media/01.5905cfaa607076924a2c.md. Lazy element type must resolve to a class or function.
Validation is passing as well.
Heres the stack trace im seeing in the console:
react-dom.production.min.js:186 Error: Minified React error #306; visit https://reactjs.org/docs/error-decoder.html?invariant=306&args[]=%2Fstatic%2Fmedia%2F01.5905cfaa607076924a2c.md&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at ws (main.e273faf5.js:2:260313)
at gu (main.e273faf5.js:2:248394)
at vu (main.e273faf5.js:2:248322)
at mu (main.e273faf5.js:2:248185)
at au (main.e273faf5.js:2:244969)
at ru (main.e273faf5.js:2:243520)
at k (main.e273faf5.js:2:291290)
at MessagePort.P (main.e273faf5.js:2:291824)
Both rerendering and reloading do not fix the issue
Because people seem to think it's kind of a nice pattern.
async function updateUser(dispatch, user, updates) {
dispatch({type: 'start update', updates})
try {
const updatedUser = await userClient.updateUser(user, updates)
dispatch({type: 'finish update', updatedUser})
return updatedUser
} catch (error) {
dispatch({type: 'fail update', error})
throw error
}
}
While node setup
worked without error on a clone of the repo / next2 branch, after fork one of the test fails.
Cf. attached log.
When going through this exercise I figured I'd follow the warning advice and use initialOn
to test my changes. That's how I came across that it wasn't working as expected. I also noticed the reducer
prop also wasn't being passed through.
I reckon passing through initialOn
is worth changing given it's related to the warning message being printed; reducer
not so much. Thoughts?
I'm following along with your course and exercise 2 gives me this error when I implement your solution:
Warning: Invalid value for prop `toggle` on <span> tag. Either remove it from the element, or pass a string or number value to keep it in the DOM.
The toggle does not function correctly
useLayoutEffect: auto-scrolling textarea -> useLayoutEffect Solution
The author describes a situation in the video: Since useEffect
is always executed after layout and paint, the UI may become torn.
The author then demonstrates this situation using the original code of 04.js
, specifically:
add message
button.The problem I'm having is that I can't reproduce the example.
I found the reason from the React 18 Working Group: In React 18, useEffect fires synchronously when it's the result of a discrete input.
You can find a more detailed description here.
I would like to give the author feedback on this matter, which is the purpose of this issue.
Here's what's going to be different in the next version of the advanced-react-patterns workshop (you can find all these changes in the next
branch until the videos are re-recorded):
./scripts/remove-ts
.default
case for our reducer switch statement because we're using typescript.useControlPropWarnings
hook and providing that for folks to just import. Now it's just one extra credit. It really should just be an open source library people can use. It's not very complicated, but it's hard to come up with on your own and doesn't really add much to your learning. A lot of people had trouble with this one and I think this change will improve it quite a bit.Hello!
I started running into this process is not defined
error yesterday. I did not run into this same error in any of the previous modules. It's happening after every hot-reload.
After a bit of googling, I found this create-react-app issue: facebook/create-react-app#11773. Looks like the same issue?
Here's my setup:
Steps to Repro:
Error will appear in console. It's happening on every page, including the isolated pages.
Once the error is triggered, I am unable to interact with the page. Buttons don't work and scrolling is disabled. This might be due to an iframe that blocks everything. This was also mentioned in the issue referenced above.
Here's the iframe I am seeing appear after the error is triggered:
Let me know if you need anything else from my end.
Thanks!
In exercise 2, workshop Advanced React Patterns, I understand how to implement the pattern but don't quite get the problem it solves.
Quoting:
We have a Toggle component that manages the state, and we want to render different parts of the UI however we want. We want control over the presentation of the UI.
🦉 The fundamental challenge you face with an API like this is the state shared between the components is implicit, meaning that the developer using your component cannot actually see or interact with the state (on) or the mechanisms for updating that state (toggle) that are being shared between the components.
So in this exercise, we’ll solve that problem by providing the compound components with the props they need implicitly using React.cloneElement.
So what is an API like this
? Because the example is not complete / working yet.
And basically the passing state from parent to children is still implicit after the pattern is applied. So what is the problem it solves here? Thanks!
Kent I'm taking ur React course and I'm here in this specific section about patterns, I want to apply the knowledge adquired refactorimg this product list which should render diferent layouts:
stacked vertically (default)
horizontal (scroll)
grid
The idea is to use the same component(s) to support all formats(DRY), here the layouts that I want to implement.
Responsible for rendering a list of products. This component decide how to be rederized the list, in vertical (default)
, horizontal (scroll)
, or grid
mode.
// ProductList.js
import React from 'react'
import {Dimensions, FlatList, View} from 'react-native'
// I'm using typescript, for the purpose of simplicity I don't put all the types
// in the code. Only the ones that define what each property of the component does.
export type ProductListProps = {
/**
* Products to display in the list
*/
products: Product[]
/**
* If true, renders items next to each other horizontally instead of stacked
* vertically.
*/
showHorizontalList?: boolean
/**
* Tell how many columns in Grid.
*/
numColumns?: number
/**
* If true, renders product list item content as column
*/
productContentAsColumn?: boolean
}
function ProductList({
products,
numColumns = 1,
showHorizontalList = false,
}) {
const getLayoutManager = () => {
const layoutManager = {}
if (showHorizontalList) {
layoutManager.horizontal = true
layoutManager.showsHorizontalScrollIndicator = false
layoutManager.ItemSeparatorComponent = ProductListItemSeparator
layoutManager.contentContainerStyle = {padding: 16}
} else {
layoutManager.numColumns = numColumns
}
return layoutManager
}
const renderItemRow = ({item}) => (
<ProductListItem
product={item}
viewContainerStyle={{
width: Dimensions.get('window').width / numColumns,
}}
// change item content direaction from `row` to 'column'
columnContainerStyle={{flexDirection: 'column'}}
/>
)
return (
<FlatList
{...getLayoutManager()}
// Pass a changing value to the `key` prop to update the columns number on the fly
key={numColumns}
data={products}
renderItem={renderItemRow}
/>
)
}
Responsible for rendering list's item content. From here, you can modify the itemContainerStyle
to decide how much space each item should occupy or contentContainerStyle
to decide whether it should be rendered as a row(default)
or column(card)
.
// ProductListItem.js
import {View} from 'react-native'
export type ProductListItemProps = {
/**
* Product to display
*/
product: FeaturedProduct
/**
* With this styles you can definde the space can be filled by each item in the list
*/
itemContainerStyle?: StyleProp<ViewStyle>
/**
* With this styles you can define if item content should render as `row` or `column`
*/
itemContentStyle?: StyleProp<ViewStyle>
}
function ProductListItem({
product,
itemContainerStyle = {},
itemContentStyle = {},
}) {
return (
<View style={itemContainerStyle}>
<View style={[styles.row, itemContentStyle]}>
// any content can be placed here
</View>
</View>
)
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
},
})
This nested component design can be really messy(creating ProducListItem inside ProducList). I would like to know if a specific react design pattern can be applied in this case to decouple list(parent) to items(childs), taking into account that the children must access the parent's state/props in order to know what kind of layout should be rendered. I'm think that Compound Components can fit here but I'm not sure, any advice in what design pattern can I use here.
Hey,
I was wondering are there any significant advantages to throwing an error inside the reducer function?
IMHO, it is a side effect and the reducer function should not have that.
I do see what you were trying to do there but I believe it is a bad user experience even though the developer was not careful and dispatched an event that's not handled by the reducer.
Thanks.
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.