mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-28 09:29:49 +02:00
Update walkthrough docs to use change
object instead of state
(#1062)
This commit is contained in:
committed by
Ian Storm Taylor
parent
c0b4a30ce6
commit
a75899f57a
@@ -20,7 +20,7 @@ class App extends React.Component {
|
|||||||
state: initialState
|
state: initialState
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,13 +44,13 @@ class App extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
state: initialState
|
state: initialState
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a new handler which prints the key code that was pressed.
|
// Define a new handler which prints the key code that was pressed.
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
console.log(event.which)
|
console.log(event.which)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +67,9 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Okay cool, so now when you press a key in the editor, you'll see the key's code printed to the console. Not very useful, but at least we know it's working.
|
Okay cool, so now when you press a key in the editor, you'll see the key's code printed to the console. Not very useful, but at least we know it's working.
|
||||||
|
|
||||||
Now we want to make it actually change the content. For the purposes of our example, let's say we want to make it so that whenever a user types `&` we actually add `and` to the content.
|
Now we want to make it actually change the content. For the purposes of our example, let's say we want to make it so that whenever a user types `&` we actually add `and` to the content.
|
||||||
|
|
||||||
Our `onKeyDown` handler might look like this:
|
Our `onKeyDown` handler might look like this:
|
||||||
|
|
||||||
@@ -79,26 +79,21 @@ class App extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
state: initialState
|
state: initialState
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
// Return with no changes if it's not the "7" key with shift pressed.
|
// Return with no changes if it's not the "7" key with shift pressed.
|
||||||
if (event.which != 55 || !event.shiftKey) return
|
if (event.which != 55 || !event.shiftKey) return
|
||||||
|
|
||||||
// Prevent the ampersand character from being inserted.
|
// Prevent the ampersand character from being inserted.
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
// Change the state by inserting "and" at the cursor's position.
|
// Change the state by inserting "and" at the cursor's position.
|
||||||
const newState = state
|
change.insertText('and')
|
||||||
.change()
|
return true
|
||||||
.insertText('and')
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
// Return the new state, which will cause the editor to update it.
|
|
||||||
return newState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@@ -22,20 +22,18 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const isCode = state.blocks.some(block => block.type == 'code')
|
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||||
|
|
||||||
return state
|
change.setBlock(isCode ? 'paragraph' : 'code')
|
||||||
.change()
|
return true
|
||||||
.setBlock(isCode ? 'paragraph' : 'code')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -65,12 +63,12 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (!event.metaKey) return
|
if (!event.metaKey) return
|
||||||
|
|
||||||
// Decide what to do based on the key code...
|
// Decide what to do based on the key code...
|
||||||
@@ -78,20 +76,16 @@ class App extends React.Component {
|
|||||||
// When "B" is pressed, add a "bold" mark to the text.
|
// When "B" is pressed, add a "bold" mark to the text.
|
||||||
case 66: {
|
case 66: {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
change.addMark('bold')
|
||||||
.change()
|
return true
|
||||||
.addMark('bold')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
// When "`" is pressed, keep our existing code block logic.
|
// When "`" is pressed, keep our existing code block logic.
|
||||||
case 67: {
|
case 67: {
|
||||||
if (!event.altKey) return
|
if (!event.altKey) return
|
||||||
const isCode = state.blocks.some(block => block.type == 'code')
|
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
change.setBlock(isCode ? 'paragraph' : 'code')
|
||||||
.change()
|
return true
|
||||||
.setBlock(isCode ? 'paragraph' : 'code')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,30 +140,26 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (!event.metaKey) return
|
if (!event.metaKey) return
|
||||||
|
|
||||||
switch (event.which) {
|
switch (event.which) {
|
||||||
case 66: {
|
case 66: {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
change.toggleMark('bold')
|
||||||
.change()
|
return true
|
||||||
.toggleMark('bold')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
case 67: {
|
case 67: {
|
||||||
if (!event.altKey) return
|
if (!event.altKey) return
|
||||||
const isCode = state.blocks.some(block => block.type == 'code')
|
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
state.setBlock(isCode ? 'paragraph' : 'code')
|
||||||
.change()
|
return true
|
||||||
.setBlock(isCode ? 'paragraph' : 'code')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
In our previous example, we started with a paragraph, but we never actually told Slate anything about the `paragraph` block type. We just let it use its internal default renderer, which uses a plain old `<div>`.
|
In our previous example, we started with a paragraph, but we never actually told Slate anything about the `paragraph` block type. We just let it use its internal default renderer, which uses a plain old `<div>`.
|
||||||
|
|
||||||
But that's not all you can do. Slate lets you define any type of custom blocks you want, like block quotes, code blocks, list items, etc.
|
But that's not all you can do. Slate lets you define any type of custom blocks you want, like block quotes, code blocks, list items, etc.
|
||||||
|
|
||||||
We'll show you how. Let's start with our app from earlier:
|
We'll show you how. Let's start with our app from earlier:
|
||||||
|
|
||||||
@@ -17,22 +17,18 @@ class App extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
state: initialState
|
state: initialState
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (event.which != 55 || !event.shiftKey) return
|
if (event.which != 55 || !event.shiftKey) return
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
const newState = state
|
change.insertText('and');
|
||||||
.change()
|
return true
|
||||||
.insertText('and')
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
return newState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -61,7 +57,7 @@ function CodeNode(props) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Pretty simple.
|
Pretty simple.
|
||||||
|
|
||||||
See the `props.attributes` reference? Slate passes attributes that should be rendered on the top-most element of your blocks, so that you don't have to build them up yourself. You **must** mix the attributes into your component.
|
See the `props.attributes` reference? Slate passes attributes that should be rendered on the top-most element of your blocks, so that you don't have to build them up yourself. You **must** mix the attributes into your component.
|
||||||
|
|
||||||
@@ -85,22 +81,18 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (event.which != 55 || !event.shiftKey) return
|
if (event.which != 55 || !event.shiftKey) return
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
const newState = state
|
change.insertText('and')
|
||||||
.change()
|
return true
|
||||||
.insertText('and')
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
return newState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -135,23 +127,21 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
// Return with no changes if it's not the "`" key with cmd/ctrl pressed.
|
// Return with no changes if it's not the "`" key with cmd/ctrl pressed.
|
||||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||||
|
|
||||||
// Prevent the "`" from being inserted by default.
|
// Prevent the "`" from being inserted by default.
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
// Otherwise, set the currently selected blocks type to "code".
|
// Otherwise, set the currently selected blocks type to "code".
|
||||||
return state
|
change.setBlock('code')
|
||||||
.change()
|
return true
|
||||||
.setBlock('code')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -187,25 +177,22 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
// Determine whether any of the currently selected blocks are code blocks.
|
// Determine whether any of the currently selected blocks are code blocks.
|
||||||
const isCode = state.blocks.some(block => block.type == 'code')
|
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||||
|
|
||||||
// Toggle the block type depending on `isCode`.
|
// Toggle the block type depending on `isCode`.
|
||||||
return state
|
change.setBlock(isCode ? 'paragraph' : 'code')
|
||||||
.change()
|
return true
|
||||||
.setBlock(isCode ? 'paragraph' : 'code')
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@@ -20,7 +20,7 @@ class App extends React.Component {
|
|||||||
state: Plain.deserialize('')
|
state: Plain.deserialize('')
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(state) {
|
onChange({ state }) {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,12 +238,12 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the document changes, save the serialized HTML to Local Storage.
|
// When the document changes, save the serialized HTML to Local Storage.
|
||||||
onDocumentChange = (document, state) => {
|
onDocumentChange = (document, { state }) => {
|
||||||
const string = html.serialize(state)
|
const string = html.serialize(state)
|
||||||
localStorage.setItem('content', string)
|
localStorage.setItem('content', string)
|
||||||
}
|
}
|
||||||
|
@@ -21,8 +21,8 @@ class App extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
state: Plain.deserialize(initialContent)
|
state: Plain.deserialize(initialContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class App extends React.Component {
|
|||||||
state: Plain.deserialize(initialContent)
|
state: Plain.deserialize(initialContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
|
|
||||||
// Save the state to Local Storage.
|
// Save the state to Local Storage.
|
||||||
@@ -92,7 +92,7 @@ class App extends React.Component {
|
|||||||
state: Plain.deserialize(initialContent)
|
state: Plain.deserialize(initialContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
|
|
||||||
const content = Plain.serialize(state)
|
const content = Plain.serialize(state)
|
||||||
@@ -128,12 +128,12 @@ class App extends React.Component {
|
|||||||
state: Plain.deserialize(initialContent)
|
state: Plain.deserialize(initialContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull the saving logic out into the `onDocumentChange` handler.
|
// Pull the saving logic out into the `onDocumentChange` handler.
|
||||||
onDocumentChange = (document, state) => {
|
onDocumentChange = (document, { state }) => {
|
||||||
const content = Plain.serialize(state)
|
const content = Plain.serialize(state)
|
||||||
localStorage.setItem('content', content)
|
localStorage.setItem('content', content)
|
||||||
}
|
}
|
||||||
@@ -176,11 +176,11 @@ class App extends React.Component {
|
|||||||
state: Raw.deserialize(initialContent, {terse: true})
|
state: Raw.deserialize(initialContent, {terse: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocumentChange = (document, state) => {
|
onDocumentChange = (document, { state }) => {
|
||||||
// Switch to using the Raw serializer.
|
// Switch to using the Raw serializer.
|
||||||
const content = JSON.stringify(Raw.serialize(state))
|
const content = JSON.stringify(Raw.serialize(state))
|
||||||
localStorage.setItem('content', content)
|
localStorage.setItem('content', content)
|
||||||
|
@@ -25,17 +25,15 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, state) => {
|
onKeyDown = (event, data, change) => {
|
||||||
if (!event.metaKey || event.which != 66) return
|
if (!event.metaKey || event.which != 66) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
change.toggleMark('bold')
|
||||||
.change()
|
return true
|
||||||
.toggleMark('bold')
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -73,7 +71,7 @@ function MarkHotkey(options) {
|
|||||||
|
|
||||||
// Return our "plugin" object, containing the `onKeyDown` handler.
|
// Return our "plugin" object, containing the `onKeyDown` handler.
|
||||||
return {
|
return {
|
||||||
onKeyDown(event, data, state) {
|
onKeyDown(event, data, change) {
|
||||||
// Check that the key pressed matches our `code` option.
|
// Check that the key pressed matches our `code` option.
|
||||||
if (!event.metaKey || event.which != code || event.altKey != isAltKey) return
|
if (!event.metaKey || event.which != code || event.altKey != isAltKey) return
|
||||||
|
|
||||||
@@ -81,10 +79,8 @@ function MarkHotkey(options) {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
// Toggle the mark `type`.
|
// Toggle the mark `type`.
|
||||||
return state
|
change.toggleMark(type)
|
||||||
.change()
|
return true
|
||||||
.toggleMark(type)
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +97,7 @@ function BoldMark(props) {
|
|||||||
|
|
||||||
// Initialize our bold-mark-adding plugin.
|
// Initialize our bold-mark-adding plugin.
|
||||||
const boldPlugin = MarkHotkey({
|
const boldPlugin = MarkHotkey({
|
||||||
type: 'bold',
|
type: 'bold',
|
||||||
code: 66
|
code: 66
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -120,8 +116,8 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,8 +165,8 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,14 +211,12 @@ function MarkHotkey(options) {
|
|||||||
const { type, key, isAltKey = false } = options
|
const { type, key, isAltKey = false } = options
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onKeyDown(event, data, state) {
|
onKeyDown(event, data, change) {
|
||||||
// Change the comparison to use the key name.
|
// Change the comparison to use the key name.
|
||||||
if (!event.metaKey || keycode(event.which) != key || event.altKey != isAltKey) return
|
if (!event.metaKey || keycode(event.which) != key || event.altKey != isAltKey) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
change.toggleMark(type)
|
||||||
.change()
|
return true
|
||||||
.toggleMark(type)
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,8 +248,8 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (state) => {
|
onChange = ({ state }) => {
|
||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user