2015-05-11 89 views
13

Mam ciąg znaków, który zawiera nazwę klasy (pochodzi z pliku json). Ten ciąg informuje moją klasę szablonów, który układ/szablon użyć dla danych (również w json). Problem polega na tym, że mój układ nie wyświetla się.Utwórz instancję klasy React z ciągu znaków

Home.jsx:

//a template or layout. 
var Home = React.createClass({ 
    render() { 
    return (
    <div>Home layout</div> 
    ) 
    } 
}); 

Template.jsx:

var Template = React.createClass({ 
    render: function() { 
    var Tag = this.props.template; //this is the name of the class eg. 'Home' 
    return (
     <Tag /> 
    ); 
    } 
}); 

ja nie otrzymuję żadnych błędów, ale też nie widzę układ/Home klasie. Sprawdziłem props.template i rejestruje poprawne informacje. Ponadto widzę element home w DOM. Jednak wygląda to tak:

<div id='template-holder> 
    <home></home> 
</div> 

jeśli zmienię następujący wiersz na:

var Tag = Home; 
//this works but it's not dynamic! 

Wszelkie pomysły, w jaki sposób mogę rozwiązać ten problem? Jestem pewien, że to albo prosta naprawa, albo robię coś głupiego. Pomoc byłaby doceniona. Przepraszamy, jeśli zostało to już zadane (nie mogłem go znaleźć).

Dzięki Ewan

Odpowiedz

9

To nie zadziała:

var Home = React.createClass({ ... }); 

var Component = "Home"; 
React.render(<Component />, ...); 

Jednak to będzie:

var Home = React.createClass({ ... }); 

var Component = Home; 
React.render(<Component />, ...); 

Więc po prostu trzeba znaleźć sposób mapowania między struny "Home" i klasa komponentuHome. Prosty obiekt będzie działał jako podstawowy rejestr i możesz go zbudować, jeśli potrzebujesz więcej funkcji.

var components = { 
    "Home": Home, 
    "Other": OtherComponent 
}; 

var Component = components[this.props.template]; 
+2

Dzięki, miałem nadzieję uniknąć map/linków w kodzie. Chciałbym móc dodawać szablony bez zmiany głównej podstawy kodu. Czy to nie jest możliwe? – ewan

+0

@Możesz zbudować jakiś globalny rejestr i zarejestrować każdy komponent, gdy zostanie utworzony z 'React.createClass' (np. Poprzez zawijanie go w wywołaniu funkcji lub coś podobnego), ale na pewno będziesz musiał uzyskać referencje do rzeczywistych składników . –

1

Podczas korzystania z JSX można renderować znaczniki HTML (ciągi) lub Reagować komponenty (klasy).

Kiedy robisz var tag = domu, to działa, ponieważ kompilator JSX przekształca go na adres:

var Template = React.createElement(Tag, {}); 

ze zmienną tag w tym samym zakresie i jest klasą React.

var Tag = Home = React.createClass({ 
         render() { 
         return (
         <div>Home layout</div> 
         ) 
         } 
        }); 

Kiedy robisz

var Tag = this.props.template; // example: Tag = "aClassName" 

robisz

var Template = React.createElement("aClassName", null); 

ale "aClassName" nie jest poprawny tag HTML.

Look here

5

Jeśli można żyć z posiadaniem wszystkich urządzeń w jednym module, to działa bez konieczności ręcznego mapowania klas do słownika:

import * as widgets from 'widgets'; 
    var Type = widgets[this.props.template]; 
    ... 
    <Type /> 

symbolu wieloznacznego oświadczenie import jest już słownik i kod działa jak rejestr w poprzedniej odpowiedzi.

Właściwie, sądzę, że można pracować z wieloma modułami z jednego dodatkowego mapowania:

import * as widgets from 'widgets'; 
import * as widgets2 from 'widgets2'; 

const registry = Object.assign({}, widgets, widgets2); 
const widget = registry[this.props.template]; 

Całkowicie to zrobić. W rzeczywistości myślę, że jestem.

1

Miałem ten sam problem i sam znalazłem rozwiązanie. Nie wiem, czy jest to "najlepsza przydatność", ale działa i używam go obecnie w moim rozwiązaniu.

Można po prostu skorzystać z funkcji "evil" eval, aby dynamicznie utworzyć wystąpienie komponentu reagowania. Coś jak:

function createComponent(componentName, props, children){ 
    var component = React.createElement(eval(componentName), props, children); 
    return component; 
} 

potem, nazwać to, gdzie chcesz:

var homeComponent = createComponent('Home', [props], [...children]); 

czy pasuje do Twoich potrzeb, może rozważyć coś takiego.

Mam nadzieję, że to pomaga.

+0

Nie uważam, że "eval" jest złem, chyba że użytkownik może wprowadzić wszystko, co chce. – xanderiel