প্রতিক্রিয়া / জেএসএক্স ডায়নামিক অংশের নাম


168

আমি উপাদানগুলির ধরণের ভিত্তিতে গতিশীলভাবে রেন্ডার করার চেষ্টা করছি।

উদাহরণ স্বরূপ:

var type = "Example";
var ComponentName = type + "Component";
return <ComponentName />; 
// Returns <examplecomponent />  instead of <ExampleComponent />

আমি এখানে প্রস্তাবিত সমাধানটি চেষ্টা করেছি / জেএসএক্স গতিশীল উপাদানগুলির নাম

সংকলন করার সময় এটি আমাকে একটি ত্রুটি দিয়েছে (গল্পের জন্য ব্রাউজারিফাই ব্যবহার করে)। এটি XML আশা করেছিল যেখানে আমি একটি অ্যারে সিনট্যাক্স ব্যবহার করছি ax

আমি প্রতিটি উপাদান জন্য একটি পদ্ধতি তৈরি করে এটি সমাধান করতে পারে:

newExampleComponent() {
    return <ExampleComponent />;
}

newComponent(type) {
    return this["new" + type + "Component"]();
}

তবে তার অর্থ আমি তৈরি প্রতিটি উপাদানগুলির জন্য একটি নতুন পদ্ধতি। এই সমস্যার আরও একটি মার্জিত সমাধান থাকতে হবে।

আমি পরামর্শ খুব খোলা।

উত্তর:


158

<MyComponent />সংকলন করে React.createElement(MyComponent, {}), যা প্রথম প্যারামিটার হিসাবে একটি স্ট্রিং (এইচটিএমএল ট্যাগ) বা একটি ফাংশন (রিঅ্যাক্টক্লাস) প্রত্যাশা করে।

আপনি কেবল একটি বড় অক্ষর দিয়ে শুরু হওয়া নামের সাথে একটি ভেরিয়েবলে আপনার উপাদান শ্রেণিটি সঞ্চয় করতে পারেন। প্রতিক্রিয়া উপাদানগুলি বনাম এইচটিএমএল ট্যাগগুলি দেখুন ।

var MyComponent = Components[type + "Component"];
return <MyComponent />;

সংকলন

var MyComponent = Components[type + "Component"];
return React.createElement(MyComponent, {});

5
ভবিষ্যতের {...this.props}পাঠকরাও পিতামাতার কাছ থেকে সাব টাইপযুক্ত উপাদানগুলিতে স্বচ্ছভাবে প্রপসগুলি সরবরাহ করতে দরকারী বলে মনে করবেন। লাইকreturn <MyComponent {...this.props} />
ডাঃ স্ট্রেঞ্জলভ

4
এছাড়াও আপনি আপনার গতিশীল পরিবর্তনশীল নামটি মূলধন করে তা নিশ্চিত করুন।
সাডা

28
মনে রাখবেন যে আপনার পরিবর্তনশীল উপাদান রাখা উচিত নিজেই এবং না ঠিক যেমন উপাদানের নাম একটি স্ট্রিং
টোটেমেডলি

3
যদি আপনিও ভাবছেন যে ভ্যারাকে কেন মূলধন করা দরকার ফেসবুক.
নোবিটা

3
উপাদানগুলি অপরিজ্ঞাত
নেস-ইই

144

এই জাতীয় পরিস্থিতিগুলি কীভাবে পরিচালনা করা যায় সে সম্পর্কে একটি অফিসিয়াল ডকুমেন্টেশন এখানে পাওয়া যায়: https://facebook.github.io/react/docs/jsx-in-depth.html#choosing-the-type-at-runtime

মূলত এটি বলে:

ভুল:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
    photo: PhotoStory,
    video: VideoStory
};

function Story(props) {
    // Wrong! JSX type can't be an expression.
    return <components[props.storyType] story={props.story} />;
}

সঠিক:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
    photo: PhotoStory,
    video: VideoStory
};

function Story(props) {
    // Correct! JSX type can be a capitalized variable.
    const SpecificStory = components[props.storyType];
    return <SpecificStory story={props.story} />;
}

25
খুব গুরুত্বপূর্ণ জিনিস: একটি মূলধন ভেরিয়েবল
এমপিইউ

4
এটি সরকারী দস্তাবেজ ছাড়াও এটি সহজেই সেরা উত্তর এবং সর্বাধিক কাঠামোগত সমাধান। সম্ভবত সে কারণেই এটি
ডক্সে রয়েছে

1
দুর্দান্ত উত্তরের জন্য ধন্যবাদ। নিম্নলিখিত পাঠকদের জন্য নোট করুন যে মানচিত্রের অবজেক্টের মধ্যে মানটি (মানচিত্রের অবজেক্টটি কনস্ট উপাদান এবং মানটি ফটোস্ট্রি এবং ভিডিওস্টিরি) অবশ্যই উদ্ধৃতি চিহ্ন ছাড়াই থাকতে হবে - অন্যথায়, উপাদানটি রেন্ডার করবে না এবং আপনি ত্রুটি পাবেন - আমার যদি আমি এটি মিস করি এবং সময় নষ্ট করি ...
এরেজ লাইবারম্যান

11

এমন একটি ধারক থাকতে হবে যা গতিশীলভাবে ব্যবহার করার কথা বলে এমন সমস্ত উপাদানগুলিতে উপাদানগুলির নাম ম্যাপ করে। কম্পোনেন্ট ক্লাসগুলি একটি ধারকটিতে নিবন্ধিত হওয়া উচিত কারণ মডুলার পরিবেশে অন্যথায় তাদের অ্যাক্সেসের একক জায়গা নেই। উপাদান শ্রেণিগুলি তাদের নামগুলি স্পষ্টভাবে উল্লেখ না করে তাদের নামগুলি দ্বারা চিহ্নিত করা যায় না কারণ ফাংশনটি nameউত্পাদনে ক্ষুদ্র হয়।

উপাদান মানচিত্র

এটি সরল বস্তু হতে পারে:

class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;

বা Mapউদাহরণ:

const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]);
...
const DynamicComponent = componentsMap.get(componentName);

প্লেইন অবজেক্ট আরও উপযুক্ত কারণ এটি সম্পত্তি শর্টহ্যান্ড থেকে উপকৃত হয়।

ব্যারেল মডিউল

একটি পিপা মডিউল নামে রপ্তানির সঙ্গে যেমন মানচিত্র হিসাবে কাজ করতে পারেন:

// Foo.js
export class Foo extends React.Component { ... }

// dynamic-components.js
export * from './Foo';
export * from './Bar';

// some module that uses dynamic component
import * as componentsMap from './dynamic-components';

const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;

এটি মডিউল কোড স্টাইল প্রতি এক শ্রেণির সাথে ভাল কাজ করে।

প্রসাধক

সিনট্যাকটিক চিনির জন্য শ্রেণি উপাদানগুলির সাথে সজ্জা ব্যবহারকারীদের ব্যবহার করা যেতে পারে, এটি এখনও শ্রেণীর নামগুলি স্পষ্টভাবে নির্দিষ্ট করে মানচিত্রে নিবন্ধিত করতে হবে:

const componentsMap = {};

function dynamic(Component) {
  if (!Component.displayName)
    throw new Error('no name');

  componentsMap[Component.displayName] = Component;

  return Component;
}

...

@dynamic
class Foo extends React.Component {
  static displayName = 'Foo'
  ...
}

একটি সাজসজ্জারকে কার্যক্ষম উপাদানগুলির সাথে উচ্চ-অর্ডার উপাদান হিসাবে ব্যবহার করা যেতে পারে:

const Bar = props => ...;
Bar.displayName = 'Bar';

export default dynamic(Bar);

ব্যবহারের অ-মানকdisplayName পরিবর্তে র্যান্ডম সম্পত্তি এছাড়াও ডিবাগ সুবিধা।


ধন্যবাদ! এই উপাদানটি
ম্যাপটি

10

আমি একটি নতুন সমাধান খুঁজে বের করেছি। মনে রাখবেন যে আমি ES6 মডিউলগুলি ব্যবহার করছি তাই আমি ক্লাসটি প্রয়োজন। পরিবর্তে আপনি একটি নতুন প্রতিক্রিয়া শ্রেণি সংজ্ঞায়িত করতে পারেন।

var components = {
    example: React.createFactory( require('./ExampleComponent') )
};

var type = "example";

newComponent() {
    return components[type]({ attribute: "value" });
}

1
আপনি কি defaultঅ্যাট্রিবিউটটি অ্যাক্সেস করার চেষ্টা করেছেন ? যেমন: প্রয়োজন ('./ উদাহরণসংশ্লিষ্ট')। ডিফল্ট?
খানহ হুয়া

7

যদি আপনার উপাদানগুলি বিশ্বব্যাপী হয় তবে আপনি কেবল এটি করতে পারেন:

var nameOfComponent = "SomeComponent";
React.createElement(window[nameOfComponent], {});


1
এটি সুন্দরভাবে কাজ করে, বিশেষত যদি রেলগুলি ব্যবহার করে। গৃহীত উত্তরটি আমার পক্ষে কাজ করে না, কারণ Componentsঅ্যারে সংজ্ঞায়িত হয়নি।
ভাদিম

3
বিশ্বব্যাপী স্কোবেটে (ইইউউ) ইচ্ছামত নামযুক্ত বস্তু সংযুক্ত করার পরিবর্তে, আপনাকে এমন একটি উপাদান রেজিস্ট্রি বজায় রাখা বিবেচনা করা উচিত যা আপনি নিবন্ধভুক্ত করতে পারেন এবং তারপরে প্রয়োজনের সময় থেকে উপাদানগুলির রেফারেন্সগুলি পুনরুদ্ধার করুন।
স্ল্যাশ যাই হোক না কেন

6

মোড়কের উপাদানগুলির জন্য, একটি সহজ সমাধান React.createElementহ'ল সরাসরি ব্যবহার করা (ES6 ব্যবহার করে)।

import RaisedButton from 'mui/RaisedButton'
import FlatButton from 'mui/FlatButton'
import IconButton from 'mui/IconButton'

class Button extends React.Component {
  render() {
    const { type, ...props } = this.props

    let button = null
    switch (type) {
      case 'flat': button = FlatButton
      break
      case 'icon': button = IconButton
      break
      default: button = RaisedButton
      break
    }

    return (
      React.createElement(button, { ...props, disableTouchRipple: true, disableFocusRipple: true })
    )
  }
}

আমার প্রকল্পে একই উদ্দেশ্য সহ আমার আসলে একটি উপাদান রয়েছে)
ডিজিমিড

2

উপাদান মানচিত্র সহ সমস্ত অপশন জুড়ে আমি ES6 সংক্ষিপ্ত বাক্য গঠন ব্যবহার করে মানচিত্রটি সংজ্ঞায়নের সবচেয়ে সহজ উপায় খুঁজে পাইনি:

import React from 'react'
import { PhotoStory, VideoStory } from './stories'

const components = {
    PhotoStory,
    VideoStory,
}

function Story(props) {
    //given that props.story contains 'PhotoStory' or 'VideoStory'
    const SpecificStory = components[props.story]
    return <SpecificStory/>
}

1

প্রচুর পরিমাণে উপাদান সহ মানচিত্রটি মোটেও ভাল দেখাচ্ছে না। আমি আসলে অবাক হয়েছি যে কেউ এরকম কিছু প্রস্তাব করেনি:

var componentName = "StringThatContainsComponentName";
const importedComponentModule = require("path/to/component/" + componentName).default;
return React.createElement(importedComponentModule); 

যখন আমাকে জসন অ্যারে আকারে লোড করা একটি বিশাল পরিমাণের উপাদানগুলি রেন্ডার করার প্রয়োজন হয়েছিল তখন এই একজন আমাকে সত্যই সহায়তা করেছিল।


এটি আমার পক্ষে যা কাজ করেছে তার খুব কাছাকাছি এবং সঠিক পথে আমাকে পরিচালিত করেছে। React.createElement(MyComponent)সরাসরি অনুরোধ করার চেষ্টা করে একটি ত্রুটি ছুঁড়ে দেওয়া। বিশেষত, আমি চাই না যে পিতামাতাকে সমস্ত উপাদান আমদানির জন্য (ম্যাপিংয়ে) জেনে রাখা উচিত - কারণ এটি অতিরিক্ত পদক্ষেপের মতো বলে মনে হচ্ছে। পরিবর্তে, আমি ব্যবহার const MyComponent = require("path/to/component/" + "ComponentNameString").default; return <MyComponent />
semaj1919

0

সন্দেহ করুন আমরা গতিশীল উপাদান লোডিং সহ বিভিন্ন ভিউ অ্যাক্সেস করতে চাই following নিম্নলিখিত কোডটি কোনও ইউআরএল অনুসন্ধানের স্ট্রিং থেকে পার্স করা স্ট্রিং ব্যবহার করে কীভাবে এটি সম্পাদন করতে পারে তার একটি কার্যকারী উদাহরণ দেয়।

ধরে নেওয়া যাক আমরা এই url পাথগুলি ব্যবহার করে দুটি অনন্য দৃষ্টিভঙ্গি সহ একটি পৃষ্ঠা 'স্নোজারি' অ্যাক্সেস করতে চাই:

'http://localhost:3000/snozberrys?aComponent'

এবং

'http://localhost:3000/snozberrys?bComponent'

আমরা আমাদের মতামতের নিয়ামকটিকে এটির মতো সংজ্ঞায়িত করি:

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import {
  BrowserRouter as Router,
  Route
} from 'react-router-dom'
import AComponent from './AComponent.js';
import CoBComponent sole from './BComponent.js';

const views = {
  aComponent: <AComponent />,
  console: <BComponent />
}

const View = (props) => {
  let name = props.location.search.substr(1);
  let view = views[name];
  if(view == null) throw "View '" + name + "' is undefined";
  return view;
}

class ViewManager extends Component {
  render() {
    return (
      <Router>
        <div>
          <Route path='/' component={View}/>
        </div>
      </Router>
    );
  }
}

export default ViewManager

ReactDOM.render(<ViewManager />, document.getElementById('root'));

0

ধরে নিন আমাদের একটি আছে flag, stateবা এর থেকে আলাদা নয় props:

import ComponentOne from './ComponentOne';
import ComponentTwo from './ComponentTwo';

~~~

const Compo = flag ? ComponentOne : ComponentTwo;

~~~

<Compo someProp={someValue} />

পতাকা দিয়ে Compoএক সঙ্গে ভরাট ComponentOneবা ComponentTwoএবং তারপর Compoএকটি প্রতিক্রিয়া কম্পোনেন্ট মত কাজ করতে পারে।


-1

আমি কিছুটা আলাদা অ্যাপ্রোচ ব্যবহার করেছি, কারণ আমরা সবসময় আমাদের আসল উপাদানগুলি জানি তাই আমি স্যুইচ কেস প্রয়োগ করার কথা ভাবলাম। আমার ক্ষেত্রে মোট উপাদানগুলির সংখ্যা 7-8 এর কাছাকাছি ছিল না।

getSubComponent(name) {
    let customProps = {
       "prop1" :"",
       "prop2":"",
       "prop3":"",
       "prop4":""
    }

    switch (name) {
      case "Component1": return <Component1 {...this.props} {...customProps} />
      case "Component2": return <Component2 {...this.props} {...customProps} />
      case "component3": return <component3 {...this.props} {...customProps} />

    }
  }

সবেমাত্র এই জুড়ে এসেছিল। এই এটা করতে হয়। আপনি সর্বদা আপনার উপাদানগুলি যে কোনও উপায়ে জানেন এবং সেগুলি লোড করা দরকার। সুতরাং এটি একটি দুর্দান্ত সমাধান। ধন্যবাদ।
জেক

-1

সম্পাদনা করুন: অন্যান্য উত্তরগুলি আরও ভাল, মন্তব্য দেখুন।

আমি একই সমস্যাটি এইভাবে সমাধান করেছি:

...
render : function () {
  var componentToRender = 'component1Name';
  var componentLookup = {
    component1Name : (<Component1 />),
    component2Name : (<Component2 />),
    ...
  };
  return (<div>
    {componentLookup[componentToRender]}
  </div>);
}
...

3
আপনি সম্ভবত এটি করতে চাইবেন না কারণ React.createElementআপনার অনুসন্ধান অবজেক্টের প্রতিটি উপাদানগুলির জন্য অনুরোধ করা হবে, যদিও তাদের মধ্যে একবারে কেবল একটিরই রেন্ডার করা হচ্ছে। সবচেয়ে খারাপ, renderঅভিভাবক উপাদানটির পদ্ধতিতে লুকিং অবজেক্টটি রেখে, পিতামাতাকে প্রতিবার রেন্ডার করার পরে এটি এটি আবার করবে। শীর্ষের উত্তরগুলি একই জিনিস অর্জনের একটি আরও ভাল উপায়।
ইনক্লিং করা

2
@ ইনক্লিং, আমি সম্মত এটি তখনই ছিল যখন আমি কেবল প্রতিক্রিয়া দিয়ে শুরু করছিলাম। আমি এটি লিখেছিলাম, তারপরে আমি যখন আরও ভাল জানতাম তখন সব ভুলে গিয়েছিলাম। যে ইশারা জন্য ধন্যবাদ।
হামাদ আখওয়ান্দ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.