マーケティングのランディングページを管理するためのCMSシステムを構築しています。 [ランディングページの編集]ビューで、ユーザーが編集しているランディングページの関連するスタイルシートをロードできるようにします。 Reactでこのようなことを行うにはどうすればよいですか?
私のアプリは Koa で動作する完全にReactで同型です。問題のページの基本的なコンポーネント階層は次のようになります。
App.jsx (has `<head>` tag)
└── Layout.jsx (dictates page structure, sidebars, etc.)
└── EditLandingPage.jsx (shows the landing page in edit mode)
ランディングページのデータ(ロードするスタイルシートのパスを含む)は、EditLandingPage
のComponentDidMount
で非同期にフェッチされます。
追加情報が必要な場合はお知らせください。これを理解したいと思います!
ボーナス:ページから移動するときにスタイルシートをアンロードしたいのですが、ComponentWillUnmount
で返された答えの逆を行うことができると思いますか?
反応の状態を使用して、動的にロードするスタイルシートのパスを更新するだけです。
import * as React from 'react';
export default class MainPage extends React.Component{
constructor(props){
super(props);
this.state = {stylePath: 'style1.css'};
}
handleButtonClick(){
this.setState({stylePath: 'style2.css'});
}
render(){
return (
<div>
<link rel="stylesheet" type="text/css" href={this.state.stylePath} />
<button type="button" onClick={this.handleButtonClick.bind(this)}>Click to update stylesheet</button>
</div>
)
}
};
また、reactコンポーネントとして実装しました。 npm install react-dynamic-style-loaderでインストールできます。
githubリポジトリを調べて確認してください:
https://github.com/burakhanalkan/react-dynamic-style-loader
これは最高のミックスインのテリトリティです。まず、スタイルシートを管理するヘルパーを定義します。
スタイルシートをロードし、その成功の約束を返す関数が必要です。スタイルシートは実際に負荷を検出するのに非常に正気です...
function loadStyleSheet(url){
var sheet = document.createElement('link');
sheet.rel = 'stylesheet';
sheet.href = url;
sheet.type = 'text/css';
document.head.appendChild(sheet);
var _timer;
// TODO: handle failure
return new Promise(function(resolve){
sheet.onload = resolve;
sheet.addEventListener('load', resolve);
sheet.onreadystatechange = function(){
if (sheet.readyState === 'loaded' || sheet.readyState === 'complete') {
resolve();
}
};
_timer = setInterval(function(){
try {
for (var i=0; i<document.styleSheets.length; i++) {
if (document.styleSheets[i].href === sheet.href) resolve();
} catch(e) { /* the stylesheet wasn't loaded */ }
}
}, 250);
})
.then(function(){ clearInterval(_timer); return link; });
}
まあ$#!@ ...私はただそれに負荷をかけると思っていましたが、ありません。これはテストされていないため、バグがある場合は更新してください。いくつかのブログ記事からコンパイルされています。
残りはかなり簡単です:
var mixin = {
componentWillMount: function(){
this._stylesheetPromises = [];
},
loadStyleSheet: function(name, url){
this._stylesheetPromises.Push(loadStyleSheet(url))
.then(function(link){
var update = {};
update[name] = true;
this.setState(update);
}.bind(this));
},
componentWillUnmount: function(){
this._stylesheetPromises.forEach(function(p){
// we use the promises because unmount before the download finishes is possible
p.then(function(link){
// guard against it being otherwise removed
if (link.parentNode) link.parentNode.removeChild(link);
});
});
}
};
繰り返しますが、テストされていないため、問題がある場合はこれを更新してください。
これでコンポーネントができました。
React.createClass({
getInitialState: function(){
return {foo: false};
},
componentDidMount: function(){
this.loadStyleSheet('foo', '/css/views/foo.css');
},
render: function(){
if (!this.state.foo) {
return <div />
}
// return conent that depends on styles
}
});
残りの唯一の作業は、スタイルシートをロードする前に既に存在しているかどうかを確認することです。うまくいけば、少なくともこれで正しい道に進むことができます。