Home

Awesome

Core React Components for Solid

A core set of React components and hooks for building your own Solid components and apps.

npm version Build Status Coverage Status Dependency Status

Follow this live tutorial to get you started!

Purpose

Solid is an ecosystem for people, data, and apps in which people can store their data where they want, independently of the apps they use.

⚛️ This library aims to:

  1. provide React developers with components to develop fun Solid apps 👨🏿‍💻
  2. enable React developers to build their own components for Solid 👷🏾‍♀️

Solid uses 🔗 Linked Data, so people's data from all over the Web can be connected together instead of needing to be stored in one giant space. This library makes working with Linked Data easier, too.

Example apps

These apps have already been built with React for Solid:

Install and go

First add the package:

yarn add @solid/react # or
npm install @solid/react

Then you can import components like this:

import { LoginButton, Value } from '@solid/react';

Build Solid apps from React components

The demo app will inspire you on how to use the components listed below.

👮🏻‍♀️ Authentication

Log the user in and out

You will need a copy of popup.html in your application folder.

<LoginButton popup="popup.html"/>
<LogoutButton>Log me out</LogoutButton>
// Shows LoginButton or LogoutButton depending on the user's status
<AuthButton popup="popup.html" login="Login here!" logout="Log me out"/>

Display different content to logged in users

<LoggedOut>
  <p>You are not logged in, and this is a members-only area!</p>
</LoggedOut>
<LoggedIn>
  <p>You are logged in and can see the special content.</p>
</LoggedIn>

👍🏾 Social interactions

With Solid, people can like any page or thing on the Web:

<Like/> // the current page
<Like object="https://github.com/">GitHub</Like>
<Like object="[https://ruben.verborgh.org/profile/#me].friends">Ruben's website</Like>
<Dislike object="http://dbpedia.org/resource/Poverty">poverty</Dislike>
<Follow object="https://ruben.verborgh.org/profile/#me">Ruben</Follow>

Your social interactions are stored in your own data pod. Build your own interactions with an <ActivityButton/>.

🖥️ Get data from Solid

Load data from the user and from the Web

<LoggedIn>
  <p>Welcome back, <Value src="user.firstName"/></p>
  <Image src="user.image" defaultSrc="profile.svg" className="pic"/>
  <ul>
    <li><Link href="user.inbox">Your inbox</Link></li>
    <li><Link href="user.homepage">Your homepage</Link></li>
  </ul>
</LoggedIn>

<h2>Random friend of <Name src="[https://ruben.verborgh.org/profile/#me]"/></h2>
<Value src="[https://ruben.verborgh.org/profile/#me].friends.firstName"/>

<h2>All friends</h2>
<List src="[https://ruben.verborgh.org/profile/#me].friends.firstName"/>

<h2>Random blog post</h2>
<Link href="[https://ruben.verborgh.org/profile/#me].blog[schema:blogPost]"/>

<h2>All blog posts</h2>
<List src="[https://ruben.verborgh.org/profile/#me].blog[schema:blogPost].label"/>

Create data expressions with LDflex

Solid React data components use the LDFlex language to build paths to the data you want.

For example:

Learn how to create your own LDflex expressions.

Automatically refresh when data is updated

Different Solid apps can write to the same documents at the same time. If you put components inside of <LiveUpdate>, they will refresh when data is updated externally. In the subscribe attribute, list the documents that should be tracked for updates; set it to * (default) if you want to listen to all documents accessed by your app. Use live updates sparingly, since change monitoring consumes additional resources, especially when monitoring documents on different data pods.

💪🏾 Create your own components

The Solid React library makes it easy to create your own components that interact with the current user and fetch Linked Data from the Web. This is easy thanks to hooks, introduced in React 16.8. A good way to get started is by looking at the implementation of built-in components like AuthButton, Name, and List.

Not a hooks user yet, or prefer writing components with functions instead of classes? Our higher-order components will help you out.

Identify the user

In Solid, people are identified by a WebID, a URL that points to them and leads to their data.

The useWebID hook gives you the WebID of the currently logged in user as a string, which changes automatically whenever someone logs in or out. The useLoggedIn and useLoggedOut hooks provide similar functionality, but return a boolean value.

import { useWebId, useLoggedIn, useLoggedOut } from '@solid/react';

function WebIdStatus() {
  const webId = useWebId();
  return <span>Your WebID is {webId}.</span>;
}

function Greeting() {
  const loggedOut = useLoggedOut();
  return <span>You are {loggedOut ? 'anonymous' : 'logged in' }.</span>;
}

Load data from the user or the Web

The useLDflexValue and useLDflexList hooks let you load a single result or multiple results of an LDflex expression.

import { useLDflexValue, useLDflexList } from '@solid/react';

function ConnectionCount() {
  const name = useLDflexValue('user.firstName') || 'unknown';
  const friends = useLDflexList('user.friends');
  return <span>{`${name}`} is connected to {friends.length} people.</span>;
}

Note how we convert name into a string through `${name}`. Alternatively, we could also use name.value. We do this because LDflex values are terms rather than strings, so they can have other properties like language and termType. Also, an LDflex value can be used as a path again, so you can keep on adding properties.

Finally, the useLDflex hook also returns status information about the expression. When its optional second argument is true, it returns a list.

import { List, useLDflex } from '@solid/react';

function BlogPosts({ author = 'https://ruben.verborgh.org/profile/#me' }) {
  const expression = `[${author}].blog[schema:blogPost].label`;
  const [posts, pending, error] = useLDflex(expression, true);

  if (pending)
    return <span>loading <em>({posts.length} posts so far)</em></span>;
  if (error)
    return <span>loading failed: {error.message}</span>;

  return <ul>{posts.map((label, index) =>
           <li key={index}>{`${label}`}</li>)}
         </ul>;
}

If your components should automatically refresh on updates when placed inside of a <LiveUpdate> component, use the useLiveUpdate hook (already included in all 3 useLDflex hooks). It returns the latest update as { timestamp, url }.

License

©2018–present Ruben Verborgh, MIT License.