Draft-js: Question: Recommended method for custom components in docs

Created on 26 Nov 2016  路  6Comments  路  Source: facebook/draft-js

I have a question that nobody else can answer me:

Why for custom components, in official docs, we use only atomic type of block and decide what kind of component we need render based on block metadata (like entity type)?

Why we did not use custom block type instead? Actually, we even not specify that this is possible and that it is necessary not to forget to use blockRenderMap for new custom type.

At first glance, using custom block type for custom components is more logical and it has some pluses (more clear and simple JSON state, for example).

But maybe there is not obvious reason not to do it? Can someone explain, please?

Most helpful comment

Either all custom blocks should be considered atomic.

I don't think it would be a good idea to force the same behavior for all custom blocks. That would just make Draft less flexible. But I think I agree with you on other points.

When fixing #203 in our application, I used the block's type property to determine the behavior for custom blocks. Those custom blocks behave the same in the editor (in regards to keyboard navigation, selection, etc.), but they look completely different (they're different components).

To us it makes sense to think about blocks as completely separate things, i.e. we don't care about what's inside the blocks when determining the behavior, just that they aren't plain text, but rather "boxed" blocks. But I guess what you mean is that it would be more appropriate to determine the behavior (again, keyboard navigation, selection etc.) based on some other property than the type?

Let's say we have three different block types :

  • image (just a video player)
  • video (just an image element)
  • event (a few text fields, dropdown fields etc.)

They would obviously look different, but in our case they would behave the exact same way. Would you like something like this instead? (please ignore the naming)

{ type: 'video', behavior: 'atomic' },
{ type: 'image', behavior: 'atomic' },
{ type: 'event', behavior: 'atomic' }

All 6 comments

A big benefit of having a common wrapper component for custom blocks is that it can potentially take care of a lot of things for us. Which in turn makes it much easier to create new block components.

Currently, the only help we get from using atomic blocks (that I can think of) is that it's easy to create/remove them. But imagine if things like selection, cursor position, keyboard movement (e.g. #203) etc. would work seamlessly for atomic blocks. To me, that would be incredibly useful.

@tobiasandersen But we can create common wrapper also for non-atomic blocks?

Yes, now we have tools for the atomic blocks, but instead it would be more convenient to have the tools to create any blocks. For example, something like that, instead AtomicBlockUtils.insertAtomicBlock.

And if in the future we will get not only the individual tools to work only with atomic blocks, but the new behavior for them - it's awful. If the tools are easy to implement by yourself (although I would like out of the box), then the behavior is nothing to be done about it.

What I'm trying to say:

  • With entities we need to describe the entities within the block, rather than actual type or metadata of that block.

  • If the block _atomicity_ imply in the future any special behavior - then atomic block should be determined not by the type of the block, but by some other property. Either all custom blocks should be considered atomic.

Either all custom blocks should be considered atomic.

I don't think it would be a good idea to force the same behavior for all custom blocks. That would just make Draft less flexible. But I think I agree with you on other points.

When fixing #203 in our application, I used the block's type property to determine the behavior for custom blocks. Those custom blocks behave the same in the editor (in regards to keyboard navigation, selection, etc.), but they look completely different (they're different components).

To us it makes sense to think about blocks as completely separate things, i.e. we don't care about what's inside the blocks when determining the behavior, just that they aren't plain text, but rather "boxed" blocks. But I guess what you mean is that it would be more appropriate to determine the behavior (again, keyboard navigation, selection etc.) based on some other property than the type?

Let's say we have three different block types :

  • image (just a video player)
  • video (just an image element)
  • event (a few text fields, dropdown fields etc.)

They would obviously look different, but in our case they would behave the exact same way. Would you like something like this instead? (please ignore the naming)

{ type: 'video', behavior: 'atomic' },
{ type: 'image', behavior: 'atomic' },
{ type: 'event', behavior: 'atomic' }

They would obviously look different, but in our case they would behave the exact same way. Would you like something like this instead? (please ignore the naming)

Yes, this is exactly what i mean :)

We have same issue - a lot of "boxed" components, that look different, but have same behaviour in editor. And we already use type of block to detect, what kind of component we need to render. That why i'm opposed to the definition of special behaviour by type of block.

Why not add the possibility to apply an entity on block?
Today we apply an entity to an space string in an atomic block - this says everything.

But I'm not really sure about this since this would be a big change.

But there is a problem with entities on empty space entities:
When you delete the atomic block with backspace the space string is moved to the upper block. So blockRendererFn will not render the entity because the atomic block was removed. But in the state the space with the entity is moved to the upper block.

Isn't a big hack after all, using entities on blank characters to present non-text content? I'm afraid of falling into dead end with custom (non-atomic) blocks, but I feel it's more right to do it that way.

What "atomic" does mean at all? It is non-divisible? It is non-textual? What is the main difference (in behavior, not appearance) between, let's say, header and image? I'd say header may be easily converted to paragraph or quote and the other way around, without loosing any content. In contrast, converting image to header or image to video is not possible (in general, I can see one may want to implement some custom conversion rules, like video -> image or image with caption -> paragraph). If that is decision boundary indeed in blocks classification, why header-one and blockquote aren't of the same nonatomic type, distinguishable by some hacky-blank-character-entity?

To sum it up, maybe I miss some point, but current design looks like legacy for me. It's nothing bad after all. I just wish to know reasoning behind it and plan for the future, if there is any. Should we continue using atomic as a base for custom blocks of any kind and only build on top of it, or maybe to develop something different, find a new path, possibly more appropriate for wide spectrum of use cases outside Facebook? @hellendag, @zpao, @flarnie could you share your thoughts?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

flarnie picture flarnie  路  3Comments

ufo22940268 picture ufo22940268  路  3Comments

eessex picture eessex  路  3Comments

darklightblue picture darklightblue  路  3Comments

jackmatrix picture jackmatrix  路  3Comments