mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
* Add version 4 react-devtools and react-devtools-core packages which support both React Native and e.g. Safari or iframe DOM usage. * Replaces typed operations arrays with regular arrays in order to support Hermes. This is unfortunate, since in theory a typed array buffer could be more efficiently transferred between frontend and backend for the web extension, but this never actually worked properly in v8, only Spidermonkey, and it fails entirely in Hermes so for the time being- it's been removed. * Adds support for React Native (paper renderer) * Adds a style editor for react-native and react-native-web
285 lines
6.9 KiB
HTML
285 lines
6.9 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<title>TODO List</title>
|
||
|
||
<!-- DevTools -->
|
||
<script src="http://localhost:8097"></script>
|
||
|
||
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
|
||
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
|
||
|
||
<!-- Don't use this in production: -->
|
||
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
|
||
|
||
<style type="text/css">
|
||
.Input {
|
||
font-size: 1rem;
|
||
padding: 0.25rem;
|
||
}
|
||
|
||
.IconButton {
|
||
padding: 0.25rem;
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.List {
|
||
margin: 0.5rem 0 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.ListItem {
|
||
list-style-type: none;
|
||
}
|
||
|
||
.Label {
|
||
cursor: pointer;
|
||
padding: 0.25rem;
|
||
color: #555;
|
||
}
|
||
.Label:hover {
|
||
color: #000;
|
||
}
|
||
|
||
.IconButton {
|
||
padding: 0.25rem;
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="root"></div>
|
||
<script type="text/babel">
|
||
const { Fragment, useCallback, useState } = React;
|
||
|
||
function List(props) {
|
||
const [newItemText, setNewItemText] = useState("");
|
||
const [items, setItems] = useState([
|
||
{ id: 1, isComplete: true, text: "First" },
|
||
{ id: 2, isComplete: true, text: "Second" },
|
||
{ id: 3, isComplete: false, text: "Third" }
|
||
]);
|
||
const [uid, setUID] = useState(4);
|
||
|
||
const handleClick = useCallback(() => {
|
||
if (newItemText !== "") {
|
||
setItems([
|
||
...items,
|
||
{
|
||
id: uid,
|
||
isComplete: false,
|
||
text: newItemText
|
||
}
|
||
]);
|
||
setUID(uid + 1);
|
||
setNewItemText("");
|
||
}
|
||
}, [newItemText, items, uid]);
|
||
|
||
const handleKeyPress = useCallback(
|
||
event => {
|
||
if (event.key === "Enter") {
|
||
handleClick();
|
||
}
|
||
},
|
||
[handleClick]
|
||
);
|
||
|
||
const handleChange = useCallback(
|
||
event => {
|
||
setNewItemText(event.currentTarget.value);
|
||
},
|
||
[setNewItemText]
|
||
);
|
||
|
||
const removeItem = useCallback(
|
||
itemToRemove => setItems(items.filter(item => item !== itemToRemove)),
|
||
[items]
|
||
);
|
||
|
||
const toggleItem = useCallback(
|
||
itemToToggle => {
|
||
const index = items.indexOf(itemToToggle);
|
||
|
||
setItems(
|
||
items
|
||
.slice(0, index)
|
||
.concat({
|
||
...itemToToggle,
|
||
isComplete: !itemToToggle.isComplete
|
||
})
|
||
.concat(items.slice(index + 1))
|
||
);
|
||
},
|
||
[items]
|
||
);
|
||
|
||
return (
|
||
<Fragment>
|
||
<h1>List</h1>
|
||
<input
|
||
type="text"
|
||
placeholder="New list item..."
|
||
className="Input"
|
||
value={newItemText}
|
||
onChange={handleChange}
|
||
onKeyPress={handleKeyPress}
|
||
/>
|
||
<button
|
||
className="IconButton"
|
||
disabled={newItemText === ""}
|
||
onClick={handleClick}
|
||
>
|
||
<span role="img" aria-label="Add item">
|
||
➕
|
||
</span>
|
||
</button>
|
||
<ul className="List">
|
||
{items.map(item => (
|
||
<ListItem
|
||
key={item.id}
|
||
item={item}
|
||
removeItem={removeItem}
|
||
toggleItem={toggleItem}
|
||
/>
|
||
))}
|
||
</ul>
|
||
</Fragment>
|
||
);
|
||
}
|
||
|
||
function ListItem({ item, removeItem, toggleItem }) {
|
||
const handleDelete = useCallback(() => {
|
||
removeItem(item);
|
||
}, [item, removeItem]);
|
||
|
||
const handleToggle = useCallback(() => {
|
||
toggleItem(item);
|
||
}, [item, toggleItem]);
|
||
|
||
return (
|
||
<li className="ListItem">
|
||
<button className="IconButton" onClick={handleDelete}>
|
||
🗑
|
||
</button>
|
||
<label className="Label">
|
||
<input
|
||
className="Input"
|
||
checked={item.isComplete}
|
||
onChange={handleToggle}
|
||
type="checkbox"
|
||
/>{" "}
|
||
{item.text}
|
||
</label>
|
||
</li>
|
||
);
|
||
}
|
||
|
||
function SimpleValues() {
|
||
return (
|
||
<ChildComponent
|
||
string="abc"
|
||
emptyString=""
|
||
number={123}
|
||
undefined={undefined}
|
||
null={null}
|
||
nan={NaN}
|
||
infinity={Infinity}
|
||
true={true}
|
||
false={false}
|
||
/>
|
||
);
|
||
}
|
||
|
||
class Custom {
|
||
_number = 42;
|
||
get number() {
|
||
return this._number;
|
||
}
|
||
}
|
||
|
||
function CustomObject() {
|
||
return <ChildComponent customObject={new Custom()} />;
|
||
}
|
||
|
||
const object = {
|
||
string: "abc",
|
||
longString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890",
|
||
emptyString: "",
|
||
number: 123,
|
||
boolean: true,
|
||
undefined: undefined,
|
||
null: null
|
||
};
|
||
|
||
function ObjectProps() {
|
||
return (
|
||
<ChildComponent
|
||
object={{
|
||
outer: {
|
||
inner: object
|
||
}
|
||
}}
|
||
array={["first", "second", "third"]}
|
||
objectInArray={[object]}
|
||
arrayInObject={{ array: ["first", "second", "third"] }}
|
||
deepObject={{
|
||
// Known limitation: we won't go deeper than several levels.
|
||
// In the future, we might offer a way to request deeper access on demand.
|
||
a: {
|
||
b: {
|
||
c: {
|
||
d: {
|
||
e: {
|
||
f: {
|
||
g: {
|
||
h: {
|
||
i: {
|
||
j: 10
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}}
|
||
/>
|
||
);
|
||
}
|
||
|
||
function ChildComponent(props: any) {
|
||
return null;
|
||
}
|
||
|
||
function InspectableElements() {
|
||
return (
|
||
<Fragment>
|
||
<SimpleValues />
|
||
<ObjectProps />
|
||
<CustomObject />
|
||
</Fragment>
|
||
);
|
||
}
|
||
|
||
function App() {
|
||
return (
|
||
<Fragment>
|
||
<List />
|
||
<InspectableElements />
|
||
</Fragment>
|
||
);
|
||
}
|
||
|
||
ReactDOM.render(<App />, document.getElementById("root"));
|
||
</script>
|
||
</body>
|
||
</html>
|