-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
13 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,253 +1,3 @@ | ||
# React | ||
|
||
This guide will get you up and running with AD4m and React. | ||
|
||
### Installing | ||
|
||
``` | ||
npm install @perspect3vism/ad4m @perspect3vism/ad4m-connect @ad4m/react | ||
``` | ||
|
||
### Initializing | ||
|
||
Create a new React app and authorize AD4M using [ad4m-connect](https://github.com/perspect3vism/ad4m/tree/dev/connect): | ||
|
||
```jsx filename="App.ts" | ||
import Ad4mConnect from "@perspect3vism/ad4m-connect"; | ||
import { useEffect } from "react"; | ||
|
||
const options = { | ||
appName: "my-ad4m-app", | ||
appDesc: "My AD4M app", | ||
appDomain: "dev.ad4m.connect.example", | ||
appIconPath: "https://i.ibb.co/GnqjPJP/icon.png", | ||
capabilities: [{ with: { domain: "*", pointers: ["*"] }, can: ["*"] }], | ||
}; | ||
|
||
export default function App() { | ||
const ui = Ad4mConnect(options); | ||
|
||
useEffect(() => { | ||
// Connect to ADAM on mount | ||
ui.connect(); | ||
}, []); | ||
|
||
return ( | ||
<div className="App"> | ||
<h1>My AD4M APP</h1> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Display perspectives | ||
|
||
The above code will display the ad4m connection dialog the first time you run the app, but that's about it. | ||
|
||
Let's fetch and display your [perspectives](/perspectives/) from ad4m using the react helpers. | ||
|
||
To do this we'll also need to save a ref to the AD4m Client returned in `.connect()`. | ||
|
||
```jsx filename="App.ts" {2, 7, 8, 13, 16-18, 22-24} | ||
import Ad4mConnect from "@perspect3vism/ad4m-connect"; | ||
import { useEffect, useState } from "react"; | ||
|
||
const options = {...}; | ||
|
||
export default function App() { | ||
const [client, setClient] = useState(); | ||
const [perspectives, setPerspectives] = useState([]); | ||
|
||
const ui = Ad4mConnect(options); | ||
|
||
useEffect(() => { | ||
Ad4mConnect(options).then(setClient); | ||
}, []); | ||
|
||
useEffect(() => { | ||
client.perspective.all().then(setPerspectives); | ||
}, [client]); | ||
|
||
return ( | ||
<div className="App"> | ||
{perspectives.map((p) => ( | ||
<li>{p.name}</li> | ||
))} | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Create perspectives | ||
|
||
If this is your first ADAM app, the list will be empty. Let's create a button that creates a new perspective for us: | ||
|
||
```jsx filename="App.ts" {20-22, 30} | ||
import Ad4mConnect from "@perspect3vism/ad4m-connect"; | ||
import { useEffect, useState } from "react"; | ||
|
||
const options = {...}; | ||
|
||
export default function App() { | ||
const [client, setClient] = useState(); | ||
const [perspectives, setPerspectives] = useState([]); | ||
|
||
const ui = Ad4mConnect(options); | ||
|
||
useEffect(() => { | ||
Ad4mConnect(options).then(setClient); | ||
}, []); | ||
|
||
useEffect(() => { | ||
client.perspective.all().then(setPerspectives); | ||
}, [client]); | ||
|
||
const onCreate = () => { | ||
await client.perspective.add("My new perspective"); | ||
} | ||
|
||
return ( | ||
<div className="App"> | ||
{perspectives.map((p) => ( | ||
<li>{p.name}</li> | ||
))} | ||
|
||
<button onClick={() => onCreate()}>Create new</button> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Creating data | ||
|
||
Let's say we want to create a list of tasks to be completed. | ||
|
||
First, we need a task model. We can use the [SDNA](/social-dna/) helpers to create this: | ||
|
||
```jsx filename="models/Task.ts" | ||
import { SDNAClass, subjectProperty, subjectFlag } from "@perspect3vism/ad4m"; | ||
|
||
@SDNAClass({ | ||
name: "Task", | ||
}) | ||
export default class Task { | ||
@subjectFlag({ | ||
through: "flux://entry_type", | ||
value: "flux://has_task", | ||
}) | ||
type: string; | ||
|
||
@subjectProperty({ | ||
through: "rdf://title", | ||
writable: true, | ||
resolveLanguage: "literal", | ||
}) | ||
title: string; | ||
|
||
@subjectProperty({ | ||
through: "rdf://status", | ||
writable: true, | ||
resolveLanguage: "literal", | ||
}) | ||
done: boolean; | ||
} | ||
``` | ||
|
||
Cool! Now let's clean things up a bit. | ||
|
||
First we'll create a new `PerspectiveDetails` component that takes in the ID of a perspective. In this file we'll use our new Task model to display all tasks in the current perspective: | ||
|
||
```jsx filename="PerspectiveDetails.ts" | ||
import { usePerspective } from "@adam/react"; | ||
import { useEntries } from "@fluxapp/react"; | ||
import Task from "./models/Task"; | ||
|
||
export default function PerspectiveDetails({ id: string }) { | ||
const myPerspective = usePerspective(id); | ||
|
||
const { entries: tasks } = useEntries({ | ||
perspective: myPerspective, | ||
model: Model, | ||
}); | ||
|
||
return ( | ||
<div> | ||
<h2>{myPerspective.name}</h2> | ||
<p>Tasks:</p> | ||
<ul> | ||
{tasks.map((task) => ( | ||
<li> | ||
{task.name} - {task.status} | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
Include the newly created component in our `App.ts` file: | ||
|
||
```jsx filename="App.ts" {4,14} | ||
import Ad4mConnect from "@perspect3vism/ad4m-connect"; | ||
import { useEffect } from "react"; | ||
import { usePerspectives } from "@adam/react"; | ||
import PerspectiveDetails from "/components/PerspectiveDetails"; | ||
|
||
const options = {...}; | ||
|
||
export default function App() { | ||
// ... | ||
|
||
return ( | ||
<div className="App"> | ||
{myPerspectives.map((p) => ( | ||
<PerspectiveDetails id={p.id} /> | ||
))} | ||
|
||
<button onClick={() => onCreate()}>Create new</button> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
Finally, let's add a simple form to allow us to create new tasks inside PerspectiveDetails: | ||
|
||
```jsx filename="PerspectiveDetails.ts" {1, 8, 15-18, 32-33} | ||
import { useState } from "react"; | ||
import { usePerspective } from "@adam/react"; | ||
import { useEntries } from "@fluxapp/react"; | ||
import Task from "./models/Task"; | ||
|
||
export default function PerspectiveDetails({ id: string }) { | ||
const myPerspective = usePerspective(id); | ||
const [taskName, setTaskName] = useState(""); | ||
|
||
const { entries: tasks } = useEntries({ | ||
perspective, | ||
model: Model, | ||
}); | ||
|
||
function createTask() { | ||
model.create({ title: taskName, status: "incomplete" }); | ||
setTaskName(""); | ||
} | ||
|
||
return ( | ||
<div> | ||
<h2>{myPerspective.name}</h2> | ||
<p>Tasks:</p> | ||
<ul> | ||
{tasks.map((task) => ( | ||
<li> | ||
{task.name} - {task.status} | ||
</li> | ||
))} | ||
</ul> | ||
|
||
<input name="taskName" onChange={(e) => setTaskName(e.target.value)} /> | ||
<button onClick={() => createTask()}>Create new task</button> | ||
</div> | ||
); | ||
} | ||
``` | ||
Coming soon! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters