React animation / ReactCSSTransitionGroup - reactjs

How would you make the following link - a spinner - work with reactjs
http://codepen.io/awesome/pen/znGwr
I am using webpack:
{ test: /\.css$/, loader: "style-loader!css-loader" }
I know the css is working from other settings.
I have tried the following, using the same css file(copy paste into local css ).
Updated: I do "return" the element, but did not write it in here. Felix Kling, thanks for noting this.
ES6:
render(){
return
<ReactCSSTransitionGroup transitionName="spinner" >
<div key='test' className="spinner"></div>
</ReactCSSTransitionGroup>
}
or
render(){
return
<div key='test' className="spinner"></div>
}
This(both) just gives me a circle and no animation.

Since you asked in your comments for an answer...
I believe the problem is that you were copying over the uncompiled SCSS instead of the compiled CSS.
Hope this helps! :D

Related

How to Use SVG with React and ReasonML?

With create-react-app and JavaScript/TypeScript, I understand I'm able to "import" an SVG as noted below. How may I do so with ReasonML?
import { ReactComponent as Logo } from './logo.svg';
function App() {
return (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
}
Create React App uses webpack to transform SVG files into React components. If you’re using Reason with CRA, then all you need to do is provide a binding to the generated component. However, CRA will only transform the SVG into a component if the import statement is written exactly a certain way, which isn't how BuckleScript outputs import statements. (There's a GitHub issue about it here.) You have to import it with raw JavaScript and then bind to the imported value:
%bs.raw
{|import {ReactComponent as _Logo} from "./logo.svg"|};
module Logo = {
[#react.component] [#bs.val] external make: unit => React.element = "_Logo";
};
/* And we can use it like a regular component: */
[#react.component]
let make = () =>
<div>
<Logo />
</div>;
According to the CRA docs:
The imported SVG React Component accepts a title prop along with other props that a svg element accepts.
For any of the other props you want to use, you'll have to add them to your external binding.
If you're not using CRA, then you'll need to configure your bundler to do the same transformation. I'm not familiar with the internals of CRA, but this seems to be the relevant code from its webpack configuration.
We can use SVGR to handle the webpack loading and then import the module as we normally would.
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
module: {
rules: [
//...
{
test: /\.svg$/,
use: ['#svgr/webpack'],
},
],
},
//...
};
module Logo = {
#bs.module(`../../../../src/img/logo.svg`) #react.component
external make: {.} => React.element = "default"
}
...
<Logo /> // works
source: https://blog.logrocket.com/how-to-use-svgs-in-react/
I am the author of another solution that doesn't involve webpack.
It's a tool that can transform your svg files directly into .re files: https://github.com/MoOx/react-from-svg
This can create files for react (dom) or react-native(-web) (=> files generated use react-native-svg).
Feel free to try it :)
For example you can do (when the tool is installed from npm)
$ react-from-svg src/SVGs src/SVGs/components --with-native-for-reason --remove-fill
This will turns the files from svg/SVGs into React components into src/SVGs/components compatible for React Native with the Reason syntax.
The last option remove all svg fill props so you can use them as icons.
Note that the generated components accept width, height & fill props so you can adjust them when used.
Last bonus: since webpack is not involved, you can use this transformation only when you update your SVGs files & use this code directly with a Node runtime (JSX from Reason gets removed when converted to JS so the code can be consumed directly via Node without any transformation - which can be handy for tiny static sites/pages).

How to load css provided by webpack inside an IFrame created using "react-frame-component" library?

I'm trying to render my React component inside an iframe. I got it to work by using the library "react-frame-component". The problem is that the styles are loaded outside the iframe, at the end of "head" element. I want to change it to be loaded inside the "head" of "iframe" element.
I'm using Webpack to generate the bundles with JS and CSS included and I saw that I can change where "style-loader" will load the styles by setting the option "insertInto", but this is throwing an error:
Uncaught Error: Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.
This is my React component:
import Frame from 'react-frame-component'
...
ReactDOM.render(
<Frame id="someId">
<Provider store={Store.get()}>
<Container/>
</Provider>,
</Frame>,
document.body
);
This is my "style-loader" in Webpack configuration:
{
loader: 'css-loader',
options: {
insertInto: () => document.querySelector("#someId"),
},
}
I think the problem is that the component was not rendered when webpack tried to include the styles. How to solve this?
You would need to load the styles into a temporary element as placeholder, and then use Javascript to clone those styles into the new frame.
// index.html
...
<div id="dynamic-styles"></div>
...
// webpack.config.js
...
{
loader: 'css-loader',
options: {
insertInto: () => document.getElementById("dynamic-styles"),
},
}
...
// some.js
...
const stylesContainer = document.getElementById('dynamic-styles');
const frame = document.getElementById('someID');
const frameHead = frame.contentWindow.document.head;
[...stylesContainer.children].forEach(styleNode => {
const newStyle = document.createElement('style');
newStyle.textContent = styleNode.textContent;
frameHead.appendChild(newStyle);
});
I haven't tested the above snippet but I know the concept works. I feel it gets the point across.
There may be a better way to do this but I haven't looked into it enough to figure it out yet. It'd be nice to be able to get webpack to make separate style bundles so that each configured frame could just automatically lazy load it's own dedicated bundled css

Is it possible to refer to css styles as objects in JS code?

I want to be able to do this:
import styles from 'switchstyle.css';
const Choice = function (props) {
const cssClasses = [];
if (props.active) {
// i think .active would be defined in the css file
cssClasses.push(style.active);
}
return (
<div
onClick={props.onClick}
className={cssClasses}
>
{props.label}
</div>
);
};
I saw something like that in a React book, but I cant get it to work -- I think I am missing some webpack plugin (I am guessing). THank you
This should work fine assuming you're using Webpack, except className can't take an array. A simple solution is to make it a string:
className={cssClasses.join(' ')}

web pack css-loader generated css class names with react-bootstrap

I'm using css-loader for web pack, and the configuration looks like this:
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?camelCase&modules')
}, ...]
And then in my jsx file I have something like this:
import styles from 'components/MyComponent/style.css'
export default class MyComponent extends React.Component {
render() {
return (
return <div className={styles.myComponent}>
<Media>
<Media.Left>
...
</Media.Left>
<Media.Body>
...
</Media.Body>
</Media>
</div>
)
}
}
And in my components/MyComponent/style.css file I have something like:
.myComponent .media-left {
vertical-align: middle;
}
And so my problem is, css-loader will generate random ids for both .myComponent and .media-left, which is seriously annoying. Because .media-left is a bootstrap class and I want it just left alone. Is there a way to make css-loader only generate an id for the top level css class?
You can have one loader for bootstrap and the other for the rest of your css, based on test config.
On another note, the modules part of your css-loader config is responsible random class names. You can use localIdentName config to format generated classnames to your liking.
So I figured this out. I need to use the global selector for every class that I want to remain global, something like this:
.myComponent :global(.media-left) {
vertical-align: middle;
}

this is undefined in Babel-compiled methods

I'm trying to write a small webapp with React 0.13 and ES6 syntax. I'm using webpack and babel-loader to compile:
loaders: [
{ test: /\.js/, exclude: /node_modules/, loader: "babel-loader"}
]
I'm having trouble with the this variable inside methods, getting "this is undefined" in several places throughout my code. For example:
export class PanelEditor extends React.Component {
...
update (){
if (!this.isMounted())
return;
this.setState(this.getStateFromStore());
}
...
}
The this variable should never be undefined under this conditions. However, I found that the problem might be the way Babel rewrites the code:
update: {
value: function update() {
if (!this.isMounted()) {
return;
}
this.setState(this.getStateFromStore());
}
},
In that way, it seems to me, the this variable refers to the object literal instead of the class. How can I fix this?
That's not actually the problem. It's that this is undefined, because you're not binding the update function.
You can do this in the constructor or in render. Most people do it in render.
<div onClick={this.update.bind(this)} />
Or (my preference), an arrow function which preserves this.
<div onClick={() => this.update()} />

Resources