Something that's always confused me is how many React examples show everything as components. But's let's say I only need to include some simple HTML alongside my components, like:
class Homepage extends Component {
render() {
return (
<Container>
<Hero />
<Features />
<div className="copyright">Copyright Some Company Name.</div>
</Container>
);
}
}
The div element will never be more than static text.
Should the <div> be moved into a pure component? Or is it ok to simplify the Homepage component by adding plain HTML this?
Sure it's ok. all in all it's HTML in the end. React components are set of html elements when you call the render function.
One rule of thumb i follow is: create a new component when you think a new responsibility is in order.
That div is a component just like any other, except it is a "primitive" one. There should be no problem mixing the primitive components from HTML with your own custom components.
Related
I'm very confused learning react.
For example I have very simple react component
export default function Foo(){
return(
<div>
<div>some text</div>
</div>
)
}
And I want to add a child component:
export default function Foo(){
const Bar = ()=>{
return (
<input placeholder="some input"/>
)
}
return(
<div>
<div>some text</div>
</div>
)
}
And as much as I know, I can use this component in two ways:
1. Use as function
return(
<div>
<div>some text</div>
{Bar()}
</div>
)
2. use as component:
return(
<div>
<div>some text</div>
<Bar/>
</div>
)
What exactly different between these two? I thought it was same, until I faced an issue with input field, that if I use component as <Bar/>, The focus on input field will be lost after I enter first letter
Demo here: https://codesandbox.io/s/gifted-archimedes-l7bce7?file=/src/App.js
So what is the exact problem here? I code as component all the time, as per my understand <Bar/> is same as Bar() when it return react component
Am I right or not?
Edit: I found this blog, and it very close to this question and it great too :)
https://dev.to/igor_bykov/react-calling-functional-components-as-functions-1d3l?signin=true
To be a component, function returning JSX should be used as <Component /> and not as Component().
When a functional component is used as <Component /> it will have a lifecycle and can have a state.
When a function is called directly as Component() it will just run and (probably) return something. No lifecycle, no hooks, none of the React magic.
The above 3 statement is the answer to your probem.
When you call the component as {Child()}, it does not have any lifecycle or hook and when you call as , it has it's own lifecycle and hooks this is why you are facing those problems.
For more read on this topis: Link.
I have seen your codesand box demo,
form there I think that the reason for losing focus from input field is the place where you have used useState.
Your can do two things here that's:
Either
Pass the state as props from parent to child component.
Or
use useState inside your child component as the parent does not require the state value I prefer the second way.
You can Read this for more knowledge of where to put the useState and when do you really need to use useState.
When you create a new component you can re-use that in another functional component.Whereas, If you create function then you cannot re-use in another functional component, it will have limited access to that particular functional component only.
I get the following warning when rendering my component:
Warning: A component is contentEditable and contains children
managed by React. It is now your responsibility to guarantee that none
of those nodes are unexpectedly modified or duplicated. This is
probably not intentional.
This is my component:
import React, { Component } from "react";
export default class Editable extends Component {
render() {
return (
<div contentEditable={true} onBlur={this.props.handleBlur}>
{this.props.children}
</div>
);
}
}
What is the potential problem with my code that React wants to warn me about? I did not quite understand from reading the documentation at https://reactjs.org/docs/dom-elements.html.
I imagine that my component should work exactly like an managed input field, without any problem:
this.props.children is initial value
the onBlur callback updates the props from event.target.innerHTML
the component is rendered with the new props
Setting the contenteditable html attribute allows the contents of that element to be modified in the browser. React is warning you that you have children within that element that are managed by React. React only works from the top down. Meaning it manages a model at the top level and maintains a virtual DOM representing that data, then renders the DOM tree based on that virtual DOM. Any changes you make to the DOM outside of React (such as setting contenteditable and allowing the content to be edited by a user directly in the browser) will be potentially blown away or cause problems for React when it goes to update those managed elements.
In your situation you don't care that the {this.props.children} node gets blown away because you know you're catching the changes and doing what you need to with it. It's just warning you that you better not expect that node to remain intact and accurately updated by React when you're letting the content be edited by the browser directly.
If you know what you're doing (and for now it looks like you do) then you can suppress that warning by adding suppressContentEditableWarning={true}.
Thanks #Chev! It fixed the warnings..
<p
className={editing ? 'editing' : ''}
onClick={editOnClick ? this.toggleEdit : undefined}
contentEditable={editing}
ref={(domNode) => {
this.domElm = domNode;
}}
onBlur={this.save}
onKeyDown={this.handleKeyDown}
{...this.props}
suppressContentEditableWarning={true}
>
{this.props.value}
</p>
I'd like to create a UI similar to JSFiddle using React:
A panel for HTML, CSS and JS
A preview panel
A single "Run" button that updates the preview
I'd like to use Microsoft's Monaco editor for the HTML, CSS and JS panels to get syntax highlight and autocomplete.
I've abstracted out a generic MonacoEditor component. My component hierarchy looks something like this:
<Root>
<div>HTML <MonacoEditor /></div>
<div>CSS <MonacoEditor /></div>
<div>JS <MonacoEditor /></div>
<button onClick={this.run}>Run</button>
<PreviewPanel />
</Root>
If I were implementing this UI in Vanilla JS, the run() method would call getValue() on each Monaco instance to extract the full text from each panel and generate the preview.
This becomes awkward with React, however, since the run() method can't call methods on instances of child components.
One workaround would be for the MonacoEditor to have an onUpdate prop which gets fired on every keystroke. The Root component could store the provisional contents of each panel for when the "Run" button was clicked. This is what I might do if each editor were a <textarea>. But it's a non-starter with Monaco. Serializing the text of the editor on every keystroke makes it unusably slow.
The only other approach I can think of is passing in a "getter setter" to the MonacoEditor component, e.g.:
class Root extends React.Component {
render() {
return (
<div>
<MonacoEditor setGetter={getter => this.getHTML=getter} />
<MonacoEditor setGetter={getter => this.getCSS=getter} />
<MonacoEditor setGetter={getter => this.getJS=getter} />
<button onClick={() => this.run()}>Run</button>
<PreviewPanel />
</div>
);
}
run() {
const html = this.getHTML();
const css = this.getCSS();
const js = this.getJS();
// ...
}
}
But this feels extremely awkward and counter to the idea of one-way databinding. Is there a better, more idiomatic approach?
You can checkout react-monaco-editor.
This will satisfy all your requirements! Especially getting value from the editor instance.
If not this, declare a function inside the editor component and use ref to call that function from other components.
Hope it helps!
I am using js-beautify (the html-beautify option) to format html that is being displayed on my page, it displays but it's collapsing all the html to 1 line which is obviously not ideal because it's a pain to read. It is basically trying to format HTML as Javascript because the actual html beautify is not being applied.
I'm using it in react as below inside a specific component file for that item does anyone know how to fix this?
import htmlBeautify from 'js-beautify'
const htmlString = htmlBeautify(renderToStaticMarkup(<Component />))
export default () =>
<Example staticMarkup={htmlString}>
<Component />
</Example>
Update:
<Example/> is another component that renders out a bunch of additional stuff like a markdown description.
I'm using https://github.com/alexlande/react-style-guide to create a styleguide and passing the static html markup to staticMarkup prop to display rather than just showing the react component which in this context isn't particulary useful.
So if it's silly question, please excuse me.
I'm using React Carousel Component (react-slick) for my project. What i want to achieve, inside this block i want to use my module "CarouselSlide".
<Slider {...settings}> //--> react-slick component tag
<CarouselSlide/> //--> my module
</Slider>
CarouselSlide is my react module shows single carousel slide.
Is it possible to use this way or do i have to edit "react-slick" component own source code ?
Depending on how you want to display the slides, the base react-slick my prove difficult since that component seems to display each sibling element in its own slide. The problem with using your own React component as a child for react-slick is that your component must return a single parent and there currently is no way of sending multiple sibling elements in your render function's return statement.
react-slick seems to want a setup like the following:
<Slider {...settings}>
<div>1</div>
<div>2</div>
</Slider>
Yet creating a component in React and returning
<div>1</div>
<div>2</div>
Would return an error since you need a single parent encapsulating the return statement.
Now instead if you had a more complicated component to define EACH slide you can then do something like:
<Slider {...settings}>
<MyComponent />
<MyComponent />
</Slider>
So it really boils down to how you use it. If you want to return the ENTIRE set of slides in a single component, you'll need to edit the base react-slick component to allow that.
Take a look at this jsFiddle and you can see the problem.
Yes it possible .You can components inside components.This is how react works