Why my bottom sub-component is shown on top of a page? - javascript

I created a sandbox environment to show an issue.
Basically the problem is when I click "Option 1" in a main menu, a new component appears in which a bottom sub-component (called BottomControls.js) is showed in the top of a page instead of a bottom of a page.
Also the CardContent is white instead of backgroundColor: 'rgb(225, 0, 80)' as defined in styles.js.
It seems like styles are applied incorrectly in BottomControls.js. I passed styles as a parameter to BottomControls.js from a parent component Main.js.
Does anybody know what am I doing wrong?

There were two main issues with how you were trying to use your styles:
You weren't exporting anything from ./layout/single/styles.js
You weren't using withStyles to convert the JS object into CSS classes that you can use
Here's a CodeSandbox that fixes those main issues:
Changes to Main.js:
// added
import { withStyles } from "#material-ui/core/styles";
Changed export default class extends Component
to class Main extends Component
// added to end of Main.js
const StyledMain = withStyles(styles)(Main);
export default StyledMain;
Changed cases of mystyles={styles} to mystyles={this.props.classes} (the classes prop is injected by withStyles).
Then in styles.js I added export default styles; to the bottom.

Related

Import a local module as component with sub components

I have a React component that works 'standalone'. It allows child components to be editable (dynamically) with an 'editable' state (editable = true makes children editable, editable = false does not)
import Editable from './editable'
<Editable>
<div>edit me!</div>
</Editable>
Next to this component I have some 'sub components' that could be used as children for the 'main component' (Editable). The can be used to specify other behavior for their children, when Editable's state is set to 'editable = true'. I don't want to import these sub components all separately. I know some ways to achieve this, I will specify them below the question.
But what I'm looking for is syntax like this:
import Editable from './editable'
<Editable>
<div>edit me!</div>
<Editable.Hide>
<div>don't show me when editable</div>
</Editable.Hide>
<Editable.Not>
<div>don't make me editable when editable</div>
</Editable.Not>
</Editable>
So the export needs to be structured so that the usage of the default export will result in the main component, but (somehow) the sub components can also be accessed through that same default export.
Why? Mostly my curiosity into the possibilities and I would love to use a syntax like the above.
So is it possible to structure an export to be able to use a syntax like that?
These are the ways I already know how to import components with sub components:
import Editable from './editable'
<Editable.MainComponent>
<div>edit me!</div>
<Editable.Hide>
<div>don't show me when editable</div>
</Editable.Hide>
<Editable.Not>
<div>don't make me editable when editable</div>
</Editable.Not>
</Editable.MainComponent>
If I would only want the main components, I could do this with some filestructure in the editable folder and import like this:
import EditableMainComponent from './editable/mainComponent'
<EditableMainComponent>
<div>edit me!</div>
</EditableMainComponent>
Or create a named export with only the main component in the same file.
import {EditableMainComponent} from './editable'
<EditableMainComponent>
<div>edit me!</div>
</EditableMainComponent>
Another way to go is to keep only the main component as the default export and the sub components as named exports.
I am trying to avoid usage like this:
import Editable, {EditableHide, EditableNot} from './editable'
<Editable>
<div>edit me!</div>
<EditableHide>
<div>don't show me when editable</div>
</EditableHide>
<EditableNot>
<div>don't make me editable when editable</div>
</EditableNot>
</Editable>
Because I don't want the user to have to specify all the different sub components in the import. So that could also be achieved like this:
import { * as Editable } from './editable'
<Editable.default>
<div>edit me!</div>
<Editable.Hide>
<div>don't show me when editable</div>
</Editable.Hide>
<Editable.Not>
<div>Don't make me editable when editable</div>
</Editable.Not>
</Editable.default>
If components are self-sufficient and can be used separately, it's preferable to consider them of the same value and treat all of them as named exports:
import {Editable, EditableHide, EditableNot} from './editable'
If some components aren't supposed to be used apart from main component, they can be namespaced with it.
For class components:
class Not extends Component {...}
export default class Editable extends Component {
static Not = Not;
...
}
For functional components:
const Not = props => ...;
const Editable = props => ...;
Editable.Not = Not;
export default Editable;
The advantage of the last approach is that this improves testability by mocking or spying secondary components in tests, as long as they are referred as Editable.Not and not Not inside Editable main component.
The disadvantage of the last approach is that secondary components cannot be tree-shaken, this shouldn't be done in case their footprint is large and main component can be often used without them.

Device specific style loading in react

I have an application in which I am using different views for mobile and desktop instead of going for responsive design. I am using server side rendering for my application.
Here is the code for browser starter file
import React from "react";
import App from "../shared/App";
import MobApp from "../shared/MobApp";
hydrate(<BrowserRouter>{__IS_MOBILE__ ? <MobApp /> : <App />}</BrowserRouter>
Here I render 'MobApp' component in case the site is loaded on mobile and 'App' in case the site is loaded on desktop.
Here is a dummy code for 'MobApp' component
import React,{ Component } from 'react';
import Header from './views/Mobile/layouts/Header';
import './MobApp.scss';
export class MobApp extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Header />
</div>
);
}
}
export default MobApp
As it is clear I am using import for loading component level CSS. Now 'Header' component inside this has it's own CSS import.
Problem -
If someone opens the site on desktop view, the code for 'MobApp' imports like MobApp.scss and all it's child components like 'Header' is also included. As a result I am able to get the CSS of mobile components on desktop.
What all approaches can I use to avoid this?
I have read about conditional imports and will try them out but would like to know if there is something better out there.
Also, let me know if I need to change the way I am adding CSS to my components or is there a more scalable way to do the same to avoid any future problems.

Trying to apply pure JavaScript effects to React ant-table component

I am very new to React and have recently inherited a project that was created with create-react-app. The project is partially done and I want to make the columns of a particular table adjustable (the user should drag and adjust the width). The previous developers used ant-table to create the table, which has no such feature.
I figured I could try and do this using plain js, like this fiddle: http://jsfiddle.net/thrilleratplay/epcybL4v/
However, I cannot make it work. I have included the js code as a inside index.html, have also tried calling it inside the .js file of the component.
This is my component code:
import React, {Component, PropTypes} from 'react';
import {Icon} from 'antd';
import Table from '../../components/tables/AntdTable.pg';
class SampleScreen extends Component {
render(){
return (
<Table data={this.props.availableFlavors.map(this.props.generateFruitList)}
selectRow={this.props.selectRow}
headers={this.props.tableHeaders} />
);
}
}
SampleScreen.propTypes = {
availableFlavors : PropTypes.array.isRequired,
tableHeaders: PropTypes.array.isRequired,
selectRow: PropTypes.object.isRequired,
generateFruitList: PropTypes.func.isRequired,
};
export default SampleScreen;
I am not sure if this is even possible, again, please bear with a React noob here. Any help is greatly appreciated.
Check the examples at antd website on how to create tables.
Resizable column

Markdown rendering with React Components inside at build time

I have a very specific issue with Preact/React:
I have a .md file with some text, which uses react-router's <Link> tags inside for navigation. Like this:
## Heading
<Link to="/test">Let's go here</Link>
In my Component file, I render the Markdown and import the Link Component and pass the Link-components down, using the preact-markup component:
...
import {Link} from 'react-router-dom';
import text from './text.md';
import Markup from 'preact-markup';
export default class Comp extends Component {
render() {
return <Markup markup={text} components={{Link, HashLink}} />;
}
}
For importing the markdown, I use the #nuxtjs/markdown-it-loader, which works fine. It all works as expected, but doesn't feel clean.
I would like to be able to either import the Link components inside the markdown file, which would save me some boilerplate code for every view.
Or, even better, I would like to be able to write my markdown inside the Component itself, with the appropriate imports, and compile it all to HTML at build time.
I don't like runtime components since they need downloading and parse- and render time.

Difference between HTML component and a normal component in Aurelia?

I'm starting with the standard TypeScript skeleton for my Aurelia development.
I wanted to add some code to the "nav-bar" component, so I decided to convert it from a simple HTML-only component to a regular component. To this end, I modified the require tag in my app.html from:
<require from="nav-bar.html"></require>
to
<require from="nav-bar"></require>
Next, I created a nav-bar.ts file, which contained the following code:
import {autoinject} from 'aurelia-framework';
import {customElement, bindable} from 'aurelia-framework';
// import {HttpClient} from 'aurelia-fetch-client';
#autoinject
#customElement('nav-bar')
export class NavBarClass {
public attached() {
console.log("TEST");
}
}
}
I left the nav-bar.html exactly as is. Now the program runs and the console contains the TEST value from the instantiated NavBarClass, BUT the menu that used to be displayed when nav-bar was HTML-only is now missing.
How do I get the menu back? What am I doing wrong? How does a regular component differ from an HTML-only component?
Thanks for your help,
-Greg
In a standard custom element the bindable properties are defined in the view-model:
nav-bar.js:
export class NavBar {
#bindable router;
...
...
}
In an html-only custom element, there is no view-model so the bindable properties are listed on the <template> element's bindable attribute instead:
nav-bar.html:
<template bindable="router">
...
...
</template>
Either way the nav-bar element usage is the same:
<nav-bar router.bind="router"></nav-bar>

Categories