3538 stories
·
2 followers

Distinguished 2

2 Shares

Distinguished 2

So ends my unplanned Snake-With-A-Moustache Week!

(And this is a sequel to a moustache-laden comic from 10 years ago!)

Read the whole story
emrox
3 hours ago
reply
Hamburg, Germany
ameel
10 days ago
reply
Melbourne, Australia
Share this story
Delete

Häagen-Bot

2 Shares

Häagen-Bot

And more robots.

Read the whole story
emrox
3 hours ago
reply
Hamburg, Germany
ameel
2 days ago
reply
Melbourne, Australia
Share this story
Delete

useTransition – React

1 Share

useTransition is a React Hook that lets you update the state without blocking the UI.

const [isPending, startTransition] = useTransition()


Reference

useTransition()

Call useTransition at the top level of your component to mark some state updates as Transitions.

import { useTransition } from 'react';

function TabContainer() {

const [isPending, startTransition] = useTransition();

// ...

}

See more examples below.

Parameters

useTransition does not take any parameters.

Returns

useTransition returns an array with exactly two items:

  1. The isPending flag that tells you whether there is a pending Transition.
  2. The startTransition function that lets you mark a state update as a Transition.

startTransition function

The startTransition function returned by useTransition lets you mark a state update as a Transition.

function TabContainer() {

const [isPending, startTransition] = useTransition();

const [tab, setTab] = useState('about');

function selectTab(nextTab) {

startTransition(() => {

setTab(nextTab);

});

}

// ...

}

Parameters

Returns

startTransition does not return anything.

Caveats

  • useTransition is a Hook, so it can only be called inside components or custom Hooks. If you need to start a Transition somewhere else (for example, from a data library), call the standalone startTransition instead.

  • You can wrap an update into a Transition only if you have access to the set function of that state. If you want to start a Transition in response to some prop or a custom Hook value, try useDeferredValue instead.

  • The function you pass to startTransition must be synchronous. React immediately executes this function, marking all state updates that happen while it executes as Transitions. If you try to perform more state updates later (for example, in a timeout), they won’t be marked as Transitions.

  • A state update marked as a Transition will be interrupted by other state updates. For example, if you update a chart component inside a Transition, but then start typing into an input while the chart is in the middle of a re-render, React will restart the rendering work on the chart component after handling the input update.

  • Transition updates can’t be used to control text inputs.

  • If there are multiple ongoing Transitions, React currently batches them together. This is a limitation that will likely be removed in a future release.


Usage

Marking a state update as a non-blocking Transition

Call useTransition at the top level of your component to mark state updates as non-blocking Transitions.

import { useState, useTransition } from 'react';

function TabContainer() {

const [isPending, startTransition] = useTransition();

// ...

}

useTransition returns an array with exactly two items:

  1. The isPending flag that tells you whether there is a pending Transition.
  2. The startTransition function that lets you mark a state update as a Transition.

You can then mark a state update as a Transition like this:

function TabContainer() {

const [isPending, startTransition] = useTransition();

const [tab, setTab] = useState('about');

function selectTab(nextTab) {

startTransition(() => {

setTab(nextTab);

});

}

// ...

}

Transitions let you keep the user interface updates responsive even on slow devices.

With a Transition, your UI stays responsive in the middle of a re-render. For example, if the user clicks a tab but then change their mind and click another tab, they can do that without waiting for the first re-render to finish.

The difference between useTransition and regular state updates

Example 2 of 2:

Updating the current tab without a Transition

In this example, the “Posts” tab is also artificially slowed down so that it takes at least a second to render. Unlike in the previous example, this state update is not a Transition.

Click “Posts” and then immediately click “Contact”. Notice that the app freezes while rendering the slowed down tab, and the UI becomes unresponsive. This state update is not a Transition, so a slow re-render freezed the user interface.

[ARTIFICIALLY SLOW] Rendering 500 <SlowPost />

[ARTIFICIALLY SLOW] Rendering 500 <SlowPost />


Updating the parent component in a Transition

You can update a parent component’s state from the useTransition call, too. For example, this TabButton component wraps its onClick logic in a Transition:

export default function TabButton({ children, isActive, onClick }) {

const [isPending, startTransition] = useTransition();

if (isActive) {

return <b>{children}</b>

}

return (

<button onClick={() => {

startTransition(() => {

onClick();

});

}}>

{children}

</button>

);

}

Because the parent component updates its state inside the onClick event handler, that state update gets marked as a Transition. This is why, like in the earlier example, you can click on “Posts” and then immediately click “Contact”. Updating the selected tab is marked as a Transition, so it does not block user interactions.

[ARTIFICIALLY SLOW] Rendering 500 <SlowPost />

[ARTIFICIALLY SLOW] Rendering 500 <SlowPost />


Displaying a pending visual state during the Transition

You can use the isPending boolean value returned by useTransition to indicate to the user that a Transition is in progress. For example, the tab button can have a special “pending” visual state:

function TabButton({ children, isActive, onClick }) {

const [isPending, startTransition] = useTransition();

// ...

if (isPending) {

return <b className="pending">{children}</b>;

}

// ...

Notice how clicking “Posts” now feels more responsive because the tab button itself updates right away:


Preventing unwanted loading indicators

In this example, the PostsTab component fetches some data using a Suspense-enabled data source. When you click the “Posts” tab, the PostsTab component suspends, causing the closest loading fallback to appear:

Hiding the entire tab container to show a loading indicator leads to a jarring user experience. If you add useTransition to TabButton, you can instead indicate display the pending state in the tab button instead.

Notice that clicking “Posts” no longer replaces the entire tab container with a spinner:

Read more about using Transitions with Suspense.

Note

Transitions will only “wait” long enough to avoid hiding already revealed content (like the tab container). If the Posts tab had a nested <Suspense> boundary, the Transition would not “wait” for it.


Building a Suspense-enabled router

If you’re building a React framework or a router, we recommend marking page navigations as Transitions.

function Router() {

const [page, setPage] = useState('/');

const [isPending, startTransition] = useTransition();

function navigate(url) {

startTransition(() => {

setPage(url);

});

}

// ...

This is recommended for two reasons:

Here is a tiny simplified router example using Transitions for navigations.

Note

Suspense-enabled routers are expected to wrap the navigation updates into Transitions by default.


Displaying an error to users with an error boundary

Canary

Error Boundary for useTransition is currently only available in React’s canary and experimental channels. Learn more about React’s release channels here.

If a function passed to startTransition throws an error, you can display an error to your user with an error boundary. To use an error boundary, wrap the component where you are calling the useTransition in an error boundary. Once the function passed to startTransition errors, the fallback for the error boundary will be displayed.

import { useTransition } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function AddCommentContainer() {
  return (
    <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
      <AddCommentButton />
    </ErrorBoundary>
  );
}

function addComment(comment) {
  
  if (comment == null) {
    throw new Error("Example Error: An error thrown to trigger error boundary");
  }
}

function AddCommentButton() {
  const [pending, startTransition] = useTransition();

  return (
    <button
      disabled={pending}
      onClick={() => {
        startTransition(() => {
          
          
          addComment();
        });
      }}
    >
      Add comment
    </button>
  );
}


Troubleshooting

Updating an input in a Transition doesn’t work

You can’t use a Transition for a state variable that controls an input:

const [text, setText] = useState('');

// ...

function handleChange(e) {

// ❌ Can't use Transitions for controlled input state

startTransition(() => {

setText(e.target.value);

});

}

// ...

return <input value={text} onChange={handleChange} />;

This is because Transitions are non-blocking, but updating an input in response to the change event should happen synchronously. If you want to run a Transition in response to typing, you have two options:

  1. You can declare two separate state variables: one for the input state (which always updates synchronously), and one that you will update in a Transition. This lets you control the input using the synchronous state, and pass the Transition state variable (which will “lag behind” the input) to the rest of your rendering logic.
  2. Alternatively, you can have one state variable, and add useDeferredValue which will “lag behind” the real value. It will trigger non-blocking re-renders to “catch up” with the new value automatically.

React doesn’t treat my state update as a Transition

When you wrap a state update in a Transition, make sure that it happens during the startTransition call:

startTransition(() => {

// ✅ Setting state *during* startTransition call

setPage('/about');

});

The function you pass to startTransition must be synchronous.

You can’t mark an update as a Transition like this:

startTransition(() => {

// ❌ Setting state *after* startTransition call

setTimeout(() => {

setPage('/about');

}, 1000);

});

Instead, you could do this:

setTimeout(() => {

startTransition(() => {

// ✅ Setting state *during* startTransition call

setPage('/about');

});

}, 1000);

Similarly, you can’t mark an update as a Transition like this:

startTransition(async () => {

await someAsyncFunction();

// ❌ Setting state *after* startTransition call

setPage('/about');

});

However, this works instead:

await someAsyncFunction();

startTransition(() => {

// ✅ Setting state *during* startTransition call

setPage('/about');

});


I want to call useTransition from outside a component

You can’t call useTransition outside a component because it’s a Hook. In this case, use the standalone startTransition method instead. It works the same way, but it doesn’t provide the isPending indicator.


The function I pass to startTransition executes immediately

If you run this code, it will print 1, 2, 3:

console.log(1);

startTransition(() => {

console.log(2);

setPage('/about');

});

console.log(3);

It is expected to print 1, 2, 3. The function you pass to startTransition does not get delayed. Unlike with the browser setTimeout, it does not run the callback later. React executes your function immediately, but any state updates scheduled while it is running are marked as Transitions. You can imagine that it works like this:

// A simplified version of how React works

let isInsideTransition = false;

function startTransition(scope) {

isInsideTransition = true;

scope();

isInsideTransition = false;

}

function setState() {

if (isInsideTransition) {

// ... schedule a Transition state update ...

} else {

// ... schedule an urgent state update ...

}

}

Read the whole story
emrox
21 hours ago
reply
Hamburg, Germany
Share this story
Delete

Endgame

2 Shares

Endgame

Thanks to everyone who bought stuff from the store! :loadWow: I’m getting more ‘Another Day Another Tuna’ stickers in stock ASAP!

:loadGive: Also I’m posting the final six pages of the latest Plucked Up story to my patreon this weekend! Just need to finish drawing it first!

:loadLove: Title thanks to stve3000 from the stream! :twitch:

P.S. the behind-the-scenes pack for patrons will be posted later this weekend! UP NOW!

Read the whole story
emrox
22 hours ago
reply
Hamburg, Germany
ameel
2 days ago
reply
Melbourne, Australia
Share this story
Delete

'Human intelligence'

1 Share

O, there be players that I have seen play, and heard others praise, and that highly, not to speak it profanely, that, neither having the accent of Christians nor the gait of Christian, pagan, nor man, have so strutted and bellowed that I have thought some of nature’s journeymen had made men and not made them well, they imitated humanity so abominably.

Will Shakespeare, Hamlet III(ii)

The original definition of ‘AI’, coined by John McCarthy in Stanford in 1955, was ‘the science and engineering of making intelligent machines’. To McCarthy and his Stanford colleagues, the meaning of ‘intelligent’ was too obvious to spell out any further. Marvin Minsky, writing in 1970, reiterated that: ‘Artificial intelligence is the science of making machines do things that would require intelligence if done by men’. Many definitions of ‘artificial intelligence’ in use today rely on the same assumption that computational ‘intelligence’ simply reflects what ‘intelligent people’ can do. Definitions such as here, here, here, and from today’s Stanford Centre for Human-Centred AI here all follow the same pattern. Intelligent people don’t even have to be men these days, but ‘we’ know who ‘they’ are.

In the guise of starting from something self-evident, the project of ‘artificial intelligence’ in fact serves to define what ‘intelligence’ is and how to value it, and therefore how diverse people should be valued too. Educators have good reason to be wary of the concept of ‘intelligence’ at all, but particularly as a single scale of potential that people have in measurable degrees. It is a statistical artefact that has long been scientifically discredited. It has been used to enforce racial and gender discrimination in education and to justify diverse forms of discriminatory violence, particularly over colonial subjects.

Biologist Stephen Jay Gould described the project as:

the abstraction of intelligence as a single entity, its location within the brain, its quantification as one number for each individual, and the use of these numbers to rank people in a single series of worthiness, invariably to find that oppressed and disadvantaged groups—races, classes, or sexes—are innately inferior.’ (Gould 1981: 25. Cited in Stephen Cave (2020) The Problem with Intelligence: Its Value-Laden History and the Future of AI.

The term ‘human’ is problematic for similar reasons. Unless its use is carefully qualified (and even then) ‘human’ all too often takes a particular fraction of humanity - white, anglo-european, male, educated, for example – as its reference point and norm. Most academics have enough sense of the history of these two terms - ‘human’ and ‘intelligence’ - to avoid using them in an unexamined way. Particularly when it comes to student learning, when we recognise there are a diversity of ambitions, identities, experiences, capabilities and cultures in the classroom, all of which can be resources for learning. And yet, since ‘artificial intelligence’ colonised the educational discourse, ‘human intelligence’ has begun to be used as though it is not only a real and self-evident thing, but self-evidently what education is about.

The value of this term to the AI industry is obvious. ‘Human intelligence’ is a palliative to anxieties about the restructuring and precaritsiation of work: don’t worry, there are still some things our models can’t do (yet). And yet the space of work that has not been declared computable today, or tomorrow, or the day after tomorrow is narrow and narrowing, and only the AI industry is qualified to define it. ‘Human’ in relation to ‘artificial’ intelligence turns people into props for data systems (humans in the loop). Props that make system outputs more accurate, safe, ethical, robust and useable, only to be removed once their input has been modelled and datafied. (Or, perhaps, when making AI safe and useable proves too expensive after all.)

This is what the WEF means by ‘working productively alongside AI’.

But it is not clear to me why anyone who cares about education would catch the term ‘human intelligence’ from the cynics who are throwing it our way. Not surprisingly, given the history of both terms, if you pay any attention you can hear how regressive and divisive it is. A small number of ‘human intelligences’ will be free to maximise their potential for innovation and originality, their entrepreneurial decision-making and wise leadership. So rest easy that there will be highly paid jobs for AI engineers and company executives.

However, these people can only max out their human qualities if they are set free from other kinds of work - the boring, repetitive and uncreative. We are supposed to believe that this work is being ‘automated’ for everyone’s benefit, but this is manifestly not so. Research assistants aren’t promoted to other, more interesting roles when ‘AI research assistants’ come online. Rather, the work they do is likely to become more pressured and less valued, or to disappear. There are still drivers (‘human overseers’) behind self-driving cars, annotators (‘data workers’) behind large language models, human personnel swiping left to authorise AI ‘targets’ for bombing, and teachers uploading lesson plans and topic maps for ‘teacherbots’. And it turns out there were 1000 Indian data workers behind Amazon’s ‘fully automated’ stores in the UK. The work does not vanish, it is just routinised, cheapened, denigrated, frequently offshored, and always disappeared from view.

The other ‘human’ who appears in the AI mirror is not running companies or registering patents but doing ‘emotional’ work: that is, work that has always been badly paid or removed from the sphere of paid work altogether. The work of care, service, community building, non-monetisable forms of creativity (craft, leisure, play), mending things and people who are broken. These forms of ‘human intelligence’ are not ‘increasingly prized’ at all. Instead, university managers are calculating how many student support staff can be replaced by chatbots. Academics who invest time and care in students (‘the human touch’) are threatened with redundancy. Schools are relying on volunteer counsellors to cope with the tsunami of mental distress (my local school has 13) while employing highly paid data analysts. In fact, the people who do the most to actually humanise the experience of mass education for students seem to be the most replaceable.  Enjoy the feels, because ‘emotional intelligence’ doesn’t ask for job security.

It’s funny how this happens, but it seems work that is highly rewarded because ‘uniquely human’ is most likely to be done by white, western, well educated men, preferably in STEM disciplines. While work that is undervalued because it is ‘only human’ is most likely to be shouldered by the rest of the world. And this work is constantly being reorganised as data work. Every gesture that can be captured as data is modelled, and whatever is left is rendered as a behaviour, to be governed by the model and its data-driven routines. Between highly paid ‘innovation’ and the non-computable work of the foundation economy - work that literally requires the human touch - AI is the project of datafying everything else.

A recent post on TechTarget defined the ‘important differences’ between artificial and human ‘intelligence’ in ways that make clear everything in the right hand column is already available on the left. ‘Human intelligence’ is apparently being flattered but actually being erased. These definitions are so shallow, cynical and vacuous, I can only read them as deliberate provocations to the education system that is supposed to fall on them gratefully. ‘Mental sensations and concepts of phenomena that are not present’? I can’t see that passing even ChatGPT’s floor-level bullshit detector.

What these self-serving comparisons produce is a double bind for students and intellectual workers. Submit yourself to the pace, the productivity, the datafied routines of algorithmic systems, and at the same time ‘be more human’. Be more human, so that you can add value to the algorithms. Be more human , so more of your behaviour can be modelled and used to undercut your value. Be more human so that when AI fails to meet human needs, the work required to ‘fix’ it is clearly specified and can cheaply be fulfilled.

We can see these demands being interpreted by students as both a need to produce optimised texts – according to a standardised rubric or, perhaps, to satisfy an automated grading system – and to write in ways that are demonstrably ‘human’ (whatever this means). No wonder they are anxious and confused.

I spoke about this double bind for students in a recent podcast for the UCL Writing Centre: Student writing as ‘passing’. (recording soon available from this link). I also explore some of these issues in a post on the ‘unreliable Turing test’. The problems and disruptions posed by ‘AI’ are not only for education to suffer, but the question of what it means to pass as both authentically human and valuable to the data economy is particularly pressing in the education system. It surfaces in all the concerns about assessment and academic integrity. But only to address it there is to fail to recognise the challenge that is being thrown down to universities by big tech, epistemologically and pedagogically, as well as through the more mundane challenges of draining talent, buying political influence, and competing for educational business.

I hope you enjoy these new offerings. All their human imperfections are my own.

Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete

The Intl.Segmenter object is now part of Baseline

1 Share
The JavaScript Intl.Segmenter object is now interoperable, enabling locale-sensitive text segmentation.
Read the whole story
emrox
1 day ago
reply
Hamburg, Germany
Share this story
Delete
Next Page of Stories