Skip to content

Commit b93df58

Browse files
authored
Merge pull request #50 from reactjs/sync-9aa84b19
Sync with react.dev @ 9aa84b1
2 parents 654f4dd + 96839bf commit b93df58

11 files changed

+369
-6
lines changed

src/content/learn/referencing-values-with-refs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ Sinun ei myöskään tarvitse huolehtia [mutaatioiden välttämistä](/learn/upd
284284

285285
## Ref ja DOM {/*refs-and-the-dom*/}
286286

287-
Voit osoittaa refin mihin tahansa arvoon. Kuitenkin yleisin käyttökohde refille on DOM elementin käsittely. Esimerkiksi, tämä on kätevää jos haluat kohdentaa syöttölaatikon ohjelmakoodillisesti. Kun annat refin `ref`-attribuuttiin JSX:ssä, kuten `<div ref={myRef}>`, React asettaa vastaavan DOM elementin `myRef.current`:iin. Kun elementti poistetaamn DOM:sta, React päivittää `myRef.current`:n arvoksi `null`. Voit lukea lisää tästä [Manipulating the DOM with Refs.](/learn/manipulating-the-dom-with-refs)
287+
Voit osoittaa refin mihin tahansa arvoon. Kuitenkin yleisin käyttökohde refille on DOM elementin käsittely. Esimerkiksi, tämä on kätevää jos haluat kohdentaa syöttölaatikon ohjelmakoodillisesti. Kun annat refin `ref`-attribuuttiin JSX:ssä, kuten `<div ref={myRef}>`, React asettaa vastaavan DOM elementin `myRef.current`:iin. Kun elementti poistetaan DOM:sta, React päivittää `myRef.current`:n arvoksi `null`. Voit lukea lisää tästä [Manipulating the DOM with Refs.](/learn/manipulating-the-dom-with-refs)
288288

289289
<Recap>
290290

src/content/learn/rendering-lists.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ Tässä `<Recipe {...recipe} key={recipe.id} />` on lyhytsyntaksi joka "välitt
10861086

10871087
#### Listat erottimella {/*list-with-a-separator*/}
10881088

1089-
Tämä esimerkki renderöi kuuluisan Katsushika Hokusain haikun, jokaisen rivin ollessa kääritty `<p>` tagin sisään. Tehtäväsi on sijoittaa `<hr />` erotin jokaisen kappaleen jälkeen. Lopputuloksen rakennelman pitäisi näyttää tältä:
1089+
Tämä esimerkki renderöi kuuluisan Tachibana Hokushin haikun, jokaisen rivin ollessa kääritty `<p>` tagin sisään. Tehtäväsi on sijoittaa `<hr />` erotin jokaisen kappaleen jälkeen. Lopputuloksen rakennelman pitäisi näyttää tältä:
10901090

10911091
```js
10921092
<article>

src/content/learn/start-a-new-react-project.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ npx create-next-app@latest
2626

2727
Jos olet uusi Next.js:ään, tutustu [Next.js tutoriaaliin.](https://nextjs.org/learn/foundations/about-nextjs)
2828

29-
Next.js:ää ylläpitää [Vercel](https://vercel.com/). Voit [julkaista Next.js-sovelluksen](https://nextjs.org/docs/deployment) mihin tahansa Node.js- tai serverless-ympäristöön, tai omalla palvelimellasi. Next.js tykee myös [staattista exporttia](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports), joka ei edellytä palvelinta.
29+
Next.js:ää ylläpitää [Vercel](https://vercel.com/). Voit [julkaista Next.js-sovelluksen](https://nextjs.org/docs/app/building-your-application/deploying) mihin tahansa Node.js- tai serverless-ympäristöön, tai omalla palvelimellasi. Next.js tukee myös [staattista exporttia](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports), joka ei edellytä palvelinta.
3030

3131
### Remix {/*remix*/}
3232

@@ -89,7 +89,7 @@ Nämä ominaisuudet ovat lähempänä tuotantokäyttöä joka päivä, ja olemme
8989

9090
### Next.js (App Router) {/*nextjs-app-router*/}
9191

92-
**[Next.js's App Router](https://beta.nextjs.org/docs) on Next.js:n API:en uudelleensuunnittelu, joka tähtää React-tiimin full-stack arkkitehtuurin visioon.** Se antaa sinun hakea dataa asynkronisissa komponenteissa, jotka suoritetaan palvelimella tai jopa rakennusaikana.
92+
**[Next.js's App Router](https://nextjs.org/docs) on Next.js:n API:en uudelleensuunnittelu, joka tähtää React-tiimin full-stack arkkitehtuurin visioon.** Se antaa sinun hakea dataa asynkronisissa komponenteissa, jotka suoritetaan palvelimella tai jopa rakennusaikana.
9393

9494
Next.js:ää ylläpitää [Vercel](https://vercel.com/). Voit [julkaista Next.js-sovelluksen](https://nextjs.org/docs/app/building-your-application/deploying) mihin tahansa Node.js- tai serverless-ympäristöön, tai omalla palvelimellasi. Next.js tukee myös [staattista exporttia](https://nextjs.org/docs/app/building-your-application/deploying/static-exports), joka ei vaadi palvelinta.
9595

src/content/reference/react-dom/server/renderToPipeableStream.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ Streaming does not need to wait for React itself to load in the browser, or for
288288
289289
- Data fetching with Suspense-enabled frameworks like [Relay](https://relay.dev/docs/guided-tour/rendering/loading-states/) and [Next.js](https://nextjs.org/docs/getting-started/react-essentials)
290290
- Lazy-loading component code with [`lazy`](/reference/react/lazy)
291+
- Reading the value of a Promise with [`use`](/reference/react/use)
291292
292293
Suspense **does not** detect when data is fetched inside an Effect or event handler.
293294

src/content/reference/react-dom/server/renderToReadableStream.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ Streaming does not need to wait for React itself to load in the browser, or for
287287
288288
- Data fetching with Suspense-enabled frameworks like [Relay](https://relay.dev/docs/guided-tour/rendering/loading-states/) and [Next.js](https://nextjs.org/docs/getting-started/react-essentials)
289289
- Lazy-loading component code with [`lazy`](/reference/react/lazy)
290+
- Reading the value of a Promise with [`use`](/reference/react/use)
290291
291292
Suspense **does not** detect when data is fetched inside an Effect or event handler.
292293

src/content/reference/react/Suspense.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ async function getAlbums() {
254254

255255
- Data fetching with Suspense-enabled frameworks like [Relay](https://relay.dev/docs/guided-tour/rendering/loading-states/) and [Next.js](https://nextjs.org/docs/getting-started/react-essentials)
256256
- Lazy-loading component code with [`lazy`](/reference/react/lazy)
257+
- Reading the value of a Promise with [`use`](/reference/react/use)
257258

258259
Suspense **does not** detect when data is fetched inside an Effect or event handler.
259260

src/content/reference/react/cache.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ See prior mentioned pitfalls
414414
415415
If none of the above apply, it may be a problem with how React checks if something exists in cache.
416416
417-
If your arguments are not [primatives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) (ex. objects, functions, arrays), ensure you're passing the same object reference.
417+
If your arguments are not [primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) (ex. objects, functions, arrays), ensure you're passing the same object reference.
418418
419419
When calling a memoized function, React will look up the input arguments to see if a result is already cached. React will use shallow equality of the arguments to determine if there is a cache hit.
420420
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: experimental_taintObjectReference
3+
---
4+
5+
<Wip>
6+
7+
**This API is experimental and is not available in a stable version of React yet.**
8+
9+
You can try it by upgrading React packages to the most recent experimental version:
10+
11+
- `react@experimental`
12+
- `react-dom@experimental`
13+
- `eslint-plugin-react-hooks@experimental`
14+
15+
Experimental versions of React may contain bugs. Don't use them in production.
16+
17+
This API is only available inside React Server Components.
18+
19+
</Wip>
20+
21+
22+
<Intro>
23+
24+
`taintObjectReference` lets you prevent a specific object instance from being passed to a Client Component like a `user` object.
25+
26+
```js
27+
experimental_taintObjectReference(message, object);
28+
```
29+
30+
To prevent passing a key, hash or token, see [`taintUniqueValue`](/reference/react/experimental_taintUniqueValue).
31+
32+
</Intro>
33+
34+
<InlineToc />
35+
36+
---
37+
38+
## Reference {/*reference*/}
39+
40+
### `taintObjectReference(message, object)` {/*taintobjectreference*/}
41+
42+
Call `taintObjectReference` with an object to register it with React as something that should not be allowed to be passed to the Client as is:
43+
44+
```js
45+
import {experimental_taintObjectReference} from 'react';
46+
47+
experimental_taintObjectReference(
48+
'Do not pass ALL environment variables to the client.',
49+
process.env
50+
);
51+
```
52+
53+
[See more examples below.](#usage)
54+
55+
#### Parameters {/*parameters*/}
56+
57+
* `message`: The message you want to display if the object gets passed to a Client Component. This message will be displayed as a part of the Error that will be thrown if the object gets passed to a Client Component.
58+
59+
* `object`: The object to be tainted. Functions and class instances can be passed to `taintObjectReference` as `object`. Functions and classes are already blocked from being passed to Client Components but the React's default error message will be replaced by what you defined in `message`. When a specific instance of a Typed Array is passed to `taintObjectReference` as `object`, any other copies of the Typed Array will not be tainted.
60+
61+
#### Returns {/*returns*/}
62+
63+
`experimental_taintObjectReference` returns `undefined`.
64+
65+
#### Caveats {/*caveats*/}
66+
67+
- Recreating or cloning a tainted object creates a new untained object which main contain sensetive data. For example, if you have a tainted `user` object, `const userInfo = {name: user.name, ssn: user.ssn}` or `{...user}` will create new objects which are not tainted. `taintObjectReference` only protects against simple mistakes when the object is passed through to a Client Component unchanged.
68+
69+
<Pitfall>
70+
71+
**Do not rely on just tainting for security.** Tainting an object doesn't prevent leaking of every possible derived value. For example, the clone of a tainted object will create a new untained object. Using data from a tainted object (e.g. `{secret: taintedObj.secret}`) will create a new value or object that is not tainted. Tainting is a layer of protection, a secure app will have multiple layers of protection, well designed APIs, and isolation patterns.
72+
73+
</Pitfall>
74+
75+
---
76+
77+
## Usage {/*usage*/}
78+
79+
### Prevent user data from unintentionally reaching the client {/*prevent-user-data-from-unintentionally-reaching-the-client*/}
80+
81+
A Client Component should never accept objects that carry sensitive data. Ideally, the data fetching functions should not expose data that the current user should not have access to. Sometimes mistakes happen during refactoring. To protect against this mistakes happening down the line we can "taint" the user object in our data API.
82+
83+
```js
84+
import {experimental_taintObjectReference} from 'react';
85+
86+
export async function getUser(id) {
87+
const user = await db`SELECT * FROM users WHERE id = ${id}`;
88+
experimental_taintObjectReference(
89+
'Do not pass the entire user object to the client. ' +
90+
'Instead, pick off the specific properties you need for this use case.',
91+
user,
92+
);
93+
return user;
94+
}
95+
```
96+
97+
Now whenever anyone tries to pass this object to a Client Component, an error will be thrown with the passed in error message instead.
98+
99+
<DeepDive>
100+
101+
#### Protecting against leaks in data fetching {/*protecting-against-leaks-in-data-fetching*/}
102+
103+
If you're running a Server Components environment that has access to sensitive data, you have to be careful not to pass objects straight through:
104+
105+
```js
106+
// api.js
107+
export async function getUser(id) {
108+
const user = await db`SELECT * FROM users WHERE id = ${id}`;
109+
return user;
110+
}
111+
```
112+
113+
```js
114+
import { getUser } from 'api.js';
115+
import { InfoCard } from 'components.js';
116+
117+
export async function Profile(props) {
118+
const user = await getUser(props.userId);
119+
// DO NOT DO THIS
120+
return <InfoCard user={user} />;
121+
}
122+
```
123+
124+
```js
125+
// components.js
126+
"use client";
127+
128+
export async function InfoCard({ user }) {
129+
return <div>{user.name}</div>;
130+
}
131+
```
132+
133+
Ideally, the `getUser` should not expose data that the current user should not have access to. To prevent passing the `user` object to a Client Component down the line we can "taint" the user object:
134+
135+
136+
```js
137+
// api.js
138+
import {experimental_taintObjectReference} from 'react';
139+
140+
export async function getUser(id) {
141+
const user = await db`SELECT * FROM users WHERE id = ${id}`;
142+
experimental_taintObjectReference(
143+
'Do not pass the entire user object to the client. ' +
144+
'Instead, pick off the specific properties you need for this use case.',
145+
user,
146+
);
147+
return user;
148+
}
149+
```
150+
151+
Now if anyone tries to pass the `user` object to a Client Component, an error will be thrown with the passed in error message.
152+
153+
</DeepDive>

0 commit comments

Comments
 (0)