Complete newbie to React and trying to find out how to load the HTML for components rather than inserting it directly in the render method. For example
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (
<!-- how can I provide a link to the HTML template for here? -->
);
}
}
React does not have HTML. The JSX that you write in the render method is actually compiled into JavaScript. At the core, React components are all JavaScript. The styles are also inline. Componentisation is neat in React because HTML, CSS, JavaScript (interactions) are all in one place, as JavaScript.
To insert raw HTML, React has an attribute dangerouslySetInnerHTML.
<div dangerouslySetInnerHTML={createMarkup()} />
If you want some type of organization, you can use variables to set the html and then assign that to the render functionalty, but React does not use html templates
var hello = React.createClass({
render: yourVariable
});
I think you might be confused about how JSX works.Just in case, I want to clarify that JSX is what they call "syntactic sugar", that turns React methods such as React.createElement into that XML like syntax. For instance:
var Nav;
// Input (JSX):
var app = <Nav color="blue" />;
// Output (JS):
var app = React.createElement(Nav, {color:"blue"});
(from the React docs)
So, to the best of my knowledge, the JSX syntax actually belongs in the render method. If what you are really looking for is the best way to separate and reuse purely presentational code, you should read on separating your app into Container and Presentational components
https://medium.com/#learnreact/container-components-c0e67432e005#.dzjqc8yrn
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mn9nf6lz6
Stateless/Presentational/Dumb Components are just functions that return JSX. So you could have your Template component:
import React from 'react';
//you need to import React to use JSX, as it will be expanded into React.createElement calls...
function Template(props){
return (
//...your template here...
);
}
And then your class
import React, {Component} from 'react';
export default class Login extends Component {
render() {
return (<Template {...props}/>);
}
}
}
Makes sense?
Related
I am fairly new to React and still wrapping my head around custom-hooks. I cam across a code where a custom hook was created to handle the component imports.
useComponentPalette.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
const defaultComponents = {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
export function useComponentPalette(){
return defaultComponents
}
And then in order to use the hook,
const {TodoItem, TodoList, Checkbox } = useComponentPalette()
My Question :- Does this approach provides any advantage over the regular imports in the component ? or this is an anti-pattern ?
How I usually import the components is as follows
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
function App(){
return(
<>
<TodoList/>
</>
)
}
It's not a good idea to use react hooks like this you can get the same result without react hook
// first file name.js
import {TodoEditor} from './components/TodoEditor'
import {TodoItem} from './components/TodoItem'
import {TodoList} from './components/TodoList'
import {CheckBox} from './components/CheckBox'
export default {
TodoEditor,
TodoItem,
TodoList,
CheckBox
}
//component file
import * as Component form 'first file name';
//<Component.TodoEditor/>
//or
import {TodoEditor} form 'first file name';
The way that I use react-hooks is for making my code more dry and increase it's readability, so react-hooks is not good fit for this kind of usage.
Hi #Sachin,
In my option, React JS use hook to manage reuse stateful logic between components. In other word, Hooks do well to encapsulating state and share logic. If you want to do some stateful logic or condition base logic with these components, then it's fine with that. But if you are using just without condition in the given components. Then, This Is useless for making the custom hook. You can do that without a custom hook in a simpler way.
Here is a simple way to do that:-
In components folder. I create index file, this is the entry point of all my exporting components
In that file. I export all my components, as you can see.
I use that components like this. It much better way. In my option.
import { Header, Footer, Sider } from "./components"
before using react custom hooks, we should be aware of the rationale behind it.
Customs hooks functionality was provided to reuse stateful logic. If logic doesn't require any state, we will use simple functions and if it is about components only there there are different patterns for making code general and scaleable.
So, there is no usage of custom hook in above case at all. For me, I would go with the following code for above scenario:
// components/index.tsx
import {Todo} from './todo'
import {CheckBox} from './components/CheckBox'
export {
Todo,
CheckBox
}
// componentns/todo/index.tsx
import {Editor} from './Editor'
import {Item} from './Item'
import {List} from './List'
const Todo = {
Editor,
Item,
List
}
export default Todo;
and usage will be like
import { Checkbox, Todo } from "components"
...
<Checkbox ... />
<Todo.List ...>
<Todo.Item ... >
</Todo.Editor ... />
</Todo.Item ... >
</Todo.List>
...
P.S Usage can be different based upon the logic of components, just giving an hint how we can patterns to serve our purpose.
Hope it helps.
I used npm init react-app appname which creates, among other files, App.js. In that file is a function component:
function App() {
return (
<SomeJSX />
);
}
I edited the function component into a class component, like so:
class App extends React.Component{
render() {
return (
<TheSameJSX />
);
}
}
Now, when I run npm start, I get an error:
Failed to compile
src/App.js
Line 4:19: 'React' is not defined no-undef
Search for the keywords to learn more about each error.
I imagine I need to add some setting somewhere that will automatically include React without me needing to explicitly import it at the top of every file. How do I do this? And why does this npm package not do that by default? I know a bit about javascript (and html and css), and have read a bit about React, but I am completely unaware of how npm or webpack works.
Thanks in advance!
EDIT: To clarify, I know how to import stuff with javascript. I can easily add import React from 'react'; to the file and make it work. However, I find it difficult to believe that adding an import statement to every single javascript file is the recommended method, and I don't understand why this example app wouldn't be set up so as to avoid having to do that. Am I mistaken? Do I really need to manually import the same thing over and over again within the same project? Could I set a global variable to React so that I can use it from wherever?
In your default function component you're not extending any classes and just writing a simple function
function App() {
return (
<SomeJSX />
);
}
In class component, you're in fact extending the Class Component by React.Component provided by React default export object and hence you must import it from the package
//only use one of these
import * as React from "react";
import {Component} from "react"; // you can directly extend without writing `React.` with this import
import React from "react"
So your code would be
import React from "react";
class App extends React.Component{
render() {
return (
<TheSameJSX />
);
}
}
Any of the above imports should be fine with a preference to the first and second one.
I am trying to declare two different React elements that I would like to render. The both elements are separated elements such as displayed elements (App.jsx) and the customized account system (Login.jsx). But in my test I have the same code in the both jsx file to ensure that the issue is not related to a specific part of them.
I have also created an /imports/startup/client/index.js file (called in the /client/main.js file):
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import './accounts-config.js';
import App from '/imports/ui/App.jsx';
import Login from '/imports/ui/Login.jsx';
Meteor.startup(() => {
render(<App />, document.getElementById('app'));
render(<Login />, document.getElementById('login'));
})
and the /client/main.html contains the related div tags:
...
<div id="app"></div>
<div id="login"></div>
...
The issue is that the second render is never displayed (here, the div login) and I observe that only the first render is interpreted.
All the examples that I've found only deals with a single react element. So I wonder how to use several separated react elements like it is in my html file ?
I am newbie in the meteorjs and react world , so maybe I didn't get the right philosophy...
You can make use of React 16 new feature that is portal.
For how to use ReactDOM.createPortal please refer to following link:
How to use ReactDOM.createPortal() in React 16?
I have solved my issue using only one render in the Meteor.startup(() (in my index.js).
The React doc specifies that only one render can be declared in the Meteor.startup(() (in my index.js).
https://reactjs.org/docs/components-and-props.html
My code is the following:
in my index.js
Meteor.startup(() => {
render(<App />, document.getElementById('app'));
})
The trick is that this Super component (App.jsx) has to be used to call all the other components. In my example by calling the Login component:
render() {
return (
<div className="container">
<Login />
</div>
)
}
I believe because the render() statement has an implicit return statement as well, so since it can only execute and return one, the next render statement isn't executed.
What is the major benefit of writing
import React, { Component } from 'react';
class Link extends Component {
...
}
instead of
import React from 'react';
class Link extends React.Component {
...
}
when it comes to react 15.4.x??
In my perspective and in my case (correct me if I am wrong) it does not matter at all since:
I am using a webpack2 for making my bundles;
I use code splitting to split my app code from vendor code;
I use webpack.optimize.CommonsChunkPlugin plugin with minChunks: Infinity setting to make sure that all vendor code is included only once.
From understanding how ES6 imports work I understand that by using named import of {Component} I state that I want to use only Component component in my code, which looks.. cleaner.
But since whole React package is still used in the app, I can create my classes with extension from React.Component instead of just Component and in result webpack will still produce the same amount of code and my bundle size will be the same in both cases.
Am I correct?
There is no difference, React.Component is the same object as Component, the second way is more eloquent in my opinion, because it really explains that you are using the Component object from the React library.
The first one seems to refer a member,
but, it comes from the pre modules era of javascript, where everything had to be attached to the exported global namespace (just to avoid global namespace pollution).
something that could be under the hood:
// this should be assumed as an example only.
class React { ... }
class Component { ... }
React.Component = Component;
// ES6
export {Component}
export default React;
// ES5
window.React = React;
Note: as someone said, you also need to import React because JSX needs to have it on scope, but, if you want to avoid it, you can expose React globally (window.React = React)
This import statement:
import React, { Component } from 'react';
is really doing two things. It imports the default export, under the name React (which is just a convention, you could call it what you want). It also imports a named export, Component.
The reason that the default React is imported is actually to make JSX work. When your JSX code is transpiled, then it substitutes <div> for React.DOM.div(), so React must exist otherwise things break!
Importing both things separately means that your JSX works but you get to write Component instead of React.Component in your code.
When you do import anything from "react", then the whole file is going to get included either way - any attempt to reduce the bundle size (e.g. Dead Code Elimination, Tree Shaking) is an additional, separate step, which doesn't depend on your import statements but the parts of the code that you use.
In the case of this library, the sane thing happens: the child Component of the default export refers to the same thing as the named export Component.
However, bear in mind that this isn't guaranteed to be the case! If the React library code contained the following:
export default {
Component: "foo"
};
export const Component = "bar";
Then React.Component === "foo" and Component === "bar".
I am learning to test React stateless components using the ReactTestUtils library. This is my simple component:
import React from 'react';
const Greeter = ({name,place}) => (
<h1>Hello,{name}. Welcome to the {place}.</h1>
);
export default Greeter;
This is my test spec, to get the renderIntoDocument working, I wrapped my Greeter component in a div as suggested here:
import {expect} from 'chai';
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import Greeter from '../Greeter';
describe('Greeter Components',() => {
it('renders correctly',() => {
var component = ReactTestUtils.renderIntoDocument(<div>
<Greeter name="Vamsi" place="Hotel California"/>
</div>);
var hasH1 = ReactTestUtils.findRenderedDOMComponentWithTag(component,'h1');
expect(hasH1).to.be.ok;
});
});
I get the error
findAllInRenderedTree(...): instance must be a composite component.
I am providing my code as jsbin here.
Since function components don't have an instance associated with them, you can't use them directly with render or renderIntoDocument. Attempting to wrap the function component is a good idea, unfortunately using a div doesn't work for a similar reason. DOM components also don't return a component instance, instead they return the underlying DOM node.
Which is all to say that you can't use the test utils function or native components as the "root" component you are rendering. Instead you will want to wrap your function components in a wrapper component that uses createClass or extends React.Component.
class Wrapper extends React.Component {
render() {
return this.props.children
}
}
let component = renderIntoDocument(<Wrapper><Greeter /></wrapper>
Gotcha's like this may be reason enough to make use of a third-party testing library like the popular enzyme, or my own take: teaspoon. Both abstract over issues like this by seamlessly wrapping and unwrapping function components for you, so you don't need to worry about what type of component you are trying to render.
Wrapping functional components in a <div> works for me. You just have to search for the component you want to test a little differently, i.e.
const props = { p1: "1" }
test('Foo renders correctly classed div', () => {
const cpt = TestUtils.renderIntoDocument(<div><Foo {...props} /></div>);
const myNode = ReactDOM.findDOMNode(cpt.childNodes[0]);
expect(myNode.className).toBe('my-class');
});
notice that you can target myNode for testing using cpt.childNodes[0]
In order to improve #monastic-panic's answer, my two cents:
You don't have to create a class for that. Do it dynamically:
import createReactClass from 'create-react-class';
// need to be a class component
const Clazz = createReactClass({
render: () => {
return <YourFunctionalComponentName {...props} />;
},
});
ReactTestUtils.renderIntoDocument(<Clazz />);