আমি কীভাবে রেডাক্সে এমন একটি মডেল ডায়লগ প্রদর্শন করতে পারি যা অ্যাসিঙ্ক্রোনাস ক্রিয়া করে?


240

আমি এমন একটি অ্যাপ তৈরি করছি যা কিছু পরিস্থিতিতে একটি নিশ্চিত ডায়ালগ দেখাতে হবে।

যাক আমি কিছু অপসারণ করতে চাই, তারপরে আমি এমন একটি ক্রিয়া প্রেরণ করব deleteSomething(id)যাতে কিছু হ্রাসকারী সেই ইভেন্টটি ধরে ফেলবে এবং ডায়ালগ হ্রাসকারকটিকে এটি প্রদর্শনের জন্য পূরণ করবে।

আমার সন্দেহ তখন আসে যখন এই ডায়লগ জমা দেয়।

  • এই উপাদানটি প্রেরিত প্রথম ক্রিয়া অনুসারে সঠিক ক্রিয়াটি কীভাবে প্রেরণ করতে পারে?
  • অ্যাকশন নির্মাতাকে এই যুক্তিটি পরিচালনা করতে হবে?
  • আমরা কি হ্রাসকারীর ভিতরে ক্রিয়া যুক্ত করতে পারি?

সম্পাদনা:

এটি পরিষ্কার করার জন্য:

deleteThingA(id) => show dialog with Questions => deleteThingARemotely(id)

createThingB(id) => Show dialog with Questions => createThingBRemotely(id)

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


1
আমি মনে করি আপনার ক্ষেত্রে সংলাপের অবস্থা (গোপন / প্রদর্শন) স্থানীয়। আমি ডায়ালগ প্রদর্শন / লুকানো পরিচালনা করতে প্রতিক্রিয়া অবস্থা ব্যবহার করতে পছন্দ করব to এইভাবে, "প্রথম ক্রিয়া অনুসারে যথাযথ পদক্ষেপ" প্রশ্নটি চলে যাবে।
মিং

উত্তর:


516

আমি যে পদ্ধতির পরামর্শ দিচ্ছি তা কিছুটা ভার্বোস তবে এটি জটিল অ্যাপ্লিকেশনগুলিতে বেশ ভালভাবে স্কেল করে দেখতে পেয়েছি। আপনি যখন কোনও মডেল দেখাতে চান, কোনও ক্রিয়াটি বর্ণনা করে যা কোনওটি বর্ণনা করে আপনি মডেলটি দেখতে চান তা :

মডেলটি দেখানোর জন্য অ্যাকশন প্রেরণ

this.props.dispatch({
  type: 'SHOW_MODAL',
  modalType: 'DELETE_POST',
  modalProps: {
    postId: 42
  }
})

(স্ট্রিংগুলি অবশ্যই ধ্রুবক হতে পারে; আমি সরলতার জন্য ইনলাইন স্ট্রিং ব্যবহার করছি))

মডেল রাজ্য পরিচালনা করতে একটি রিডুসার রচনা

তারপরে নিশ্চিত হয়ে নিন যে আপনার কাছে এমন একটি হ্রাসকারী রয়েছে যা কেবল এই মানগুলি গ্রহণ করে:

const initialState = {
  modalType: null,
  modalProps: {}
}

function modal(state = initialState, action) {
  switch (action.type) {
    case 'SHOW_MODAL':
      return {
        modalType: action.modalType,
        modalProps: action.modalProps
      }
    case 'HIDE_MODAL':
      return initialState
    default:
      return state
  }
}

/* .... */

const rootReducer = combineReducers({
  modal,
  /* other reducers */
})

গ্রেট! এখন, আপনি যখন কোনও অ্যাকশন প্রেরণ state.modalকরবেন, বর্তমানে দৃশ্যমান মডেল উইন্ডো সম্পর্কিত তথ্য অন্তর্ভুক্ত করার জন্য আপডেট হবে will

রুট মডেল উপাদান লিখছেন

আপনার উপাদান স্তরক্রমের মূলে, <ModalRoot>Redux স্টোরের সাথে যুক্ত একটি উপাদান যুক্ত করুন। এটি শুনতে state.modalএবং একটি উপযুক্ত মডেল উপাদান প্রদর্শন করবে , এর কাছ থেকে প্রপস ফরোয়ার্ড করবে state.modal.modalProps

// These are regular React components we will write soon
import DeletePostModal from './DeletePostModal'
import ConfirmLogoutModal from './ConfirmLogoutModal'

const MODAL_COMPONENTS = {
  'DELETE_POST': DeletePostModal,
  'CONFIRM_LOGOUT': ConfirmLogoutModal,
  /* other modals */
}

const ModalRoot = ({ modalType, modalProps }) => {
  if (!modalType) {
    return <span /> // after React v15 you can return null here
  }

  const SpecificModal = MODAL_COMPONENTS[modalType]
  return <SpecificModal {...modalProps} />
}

export default connect(
  state => state.modal
)(ModalRoot)

আমরা এখানে কি করেছি? ModalRootবর্তমান সার্চ modalTypeএবং modalPropsথেকে state.modalযা এটি সংযুক্ত করা হয়, এবং উপস্থাপনা একটি সংশ্লিষ্ট কম্পোনেন্ট যেমন DeletePostModalবাConfirmLogoutModal । প্রতিটি মডেল একটি উপাদান!

নির্দিষ্ট মডেল উপাদান রচনা

এখানে কোনও সাধারণ নিয়ম নেই। তারা শুধু যে সমস্ত উপাদান, কর্ম প্রাণবধ দোকান রাজ্য থেকে কিছু পড়তে পারেন প্রতিক্রিয়া হয় এবং মাত্র মোডাল হতে ঘটতে

উদাহরণস্বরূপ, দেখতে DeletePostModalহতে পারে:

import { deletePost, hideModal } from '../actions'

const DeletePostModal = ({ post, dispatch }) => (
  <div>
    <p>Delete post {post.name}?</p>
    <button onClick={() => {
      dispatch(deletePost(post.id)).then(() => {
        dispatch(hideModal())
      })
    }}>
      Yes
    </button>
    <button onClick={() => dispatch(hideModal())}>
      Nope
    </button>
  </div>
)

export default connect(
  (state, ownProps) => ({
    post: state.postsById[ownProps.postId]
  })
)(DeletePostModal)

DeletePostModalদোকান থেকে সংযুক্ত করা হয়, তাই এটি পোস্টের শিরোনাম প্রদর্শন এবং কোন সংযুক্ত উপাদান মত কাজ করে কিনা: এটা, কর্ম প্রাণবধ করতে পারেন তা সহhideModal যখন এটা নিজেই আড়াল করা প্রয়োজন।

একটি উপস্থাপক উপাদান আহরণ করা হচ্ছে

প্রতিটি "নির্দিষ্ট" মডেলের জন্য একই লেআউট যুক্তিকে কপি-পেস্ট করা বিশ্রী হবে। কিন্তু আপনার উপাদান আছে, তাই না? সুতরাং আপনি একটি উপস্থাপনা নিষ্কাশন করতে পারেন <Modal> উপাদানটি যা নির্দিষ্ট মডেলগুলি কী করে তা জানেন না তবে তারা কীভাবে দেখায় তা পরিচালনা করে।

তারপরে, নির্দিষ্ট মডেলগুলি যেমন DeletePostModalরেন্ডারিংয়ের জন্য এটি ব্যবহার করতে পারে:

import { deletePost, hideModal } from '../actions'
import Modal from './Modal'

const DeletePostModal = ({ post, dispatch }) => (
  <Modal
    dangerText={`Delete post ${post.name}?`}
    onDangerClick={() =>
      dispatch(deletePost(post.id)).then(() => {
        dispatch(hideModal())
      })
    })
  />
)

export default connect(
  (state, ownProps) => ({
    post: state.postsById[ownProps.postId]
  })
)(DeletePostModal)

আপনার প্রাপকদের একটি সেট নিয়ে আসা আপনার উপর নির্ভর করবে যা <Modal>আপনার অ্যাপ্লিকেশনটিতে গ্রহণ করতে পারে তবে আমি ধারণা করব যে আপনার কাছে বিভিন্ন ধরণের মডেল থাকতে পারে (যেমন তথ্য মডেল, কনফার্মেশন মডেল, ইত্যাদি) এবং তাদের জন্য বেশ কয়েকটি শৈলী।

অ্যাক্সেসিবিলিটি এবং বাইরের ক্লিক বা এস্কেপ কীতে লুকানো

মডেলগুলি সম্পর্কে সর্বশেষ গুরুত্বপূর্ণ অংশটি হ'ল ব্যবহারকারীরা যখন বাইরে ক্লিক করেন বা এস্কেপ প্রেস করেন তখন আমরা সেগুলি আড়াল করতে চাই।

এটি প্রয়োগের জন্য আপনাকে পরামর্শ দেওয়ার পরিবর্তে, আমি আপনাকে নিজে এটি প্রয়োগ না করার পরামর্শ দিচ্ছি। অ্যাক্সেসযোগ্যতার কথা বিবেচনা করে সঠিকভাবে পাওয়া শক্ত।

পরিবর্তে, আমি আপনাকে একটি অ্যাক্সেসযোগ্য অফ-শেল্ফ মডেল উপাদান যেমন ব্যবহার করার পরামর্শ দিচ্ছি react-modal। এটি সম্পূর্ণরূপে স্বনির্ধারিত, আপনি এটির ভিতরে যা কিছু চান তা রাখতে পারেন তবে এটি অ্যাক্সেসযোগ্যতাটি সঠিকভাবে পরিচালনা করে যাতে অন্ধ লোকেরা এখনও আপনার মডেলটি ব্যবহার করতে পারে।

এমনকি আপনি react-modalনিজের নিজের মধ্যে মোড়ানো করতে পারেন <Modal>যা আপনার অ্যাপ্লিকেশনগুলির জন্য নির্দিষ্ট প্রপস গ্রহণ করে এবং শিশু বোতাম বা অন্যান্য সামগ্রী তৈরি করে। এটি সব ঠিক উপাদান!

অন্যান্য পন্থা

এটি করার একাধিক উপায় রয়েছে।

কিছু লোক এই পদ্ধতির ভার্বোসটি পছন্দ করেন না এবং <Modal>এমন উপাদানগুলি পছন্দ করেন যা তারা তাদের উপাদানগুলির ভিতরে ডান "পোর্টাল" নামে একটি কৌশল দিয়ে রেন্ডার করতে পারেন । পোর্টালগুলি আপনাকে আসলে আপনার ভিতরে একটি উপাদান রেন্ডার করতে দেয় এটা করে DOM, যা মোডাল জন্য খুব সুবিধাজনক একটি পূর্ব-নির্ধারিত স্থানে প্রতিদান দেবেন।

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

আমি আপনাকে উভয় পন্থা বিবেচনা করতে, সেগুলির সাথে পরীক্ষা করার জন্য এবং আপনার অ্যাপ এবং আপনার দলের জন্য যা ভাল লাগে তা চয়ন করতে উত্সাহিত করি।


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

9
হ্যাঁ, স্পষ্টতই, এই ধরণের জিনিসটি রেডাক্স তৈরি করা সহজ করে দেয় কারণ আপনি কেবল নিজের রাজ্যটিকে অ্যারে হিসাবে পরিবর্তন করতে পারবেন। ব্যক্তিগতভাবে আমি ডিজাইনারদের সাথে কাজ করেছি যারা বিপরীতে, মডেলগুলি একচেটিয়া হতে চেয়েছিল, তাই আমি যে পদ্ধতিটি লিখেছি তা দুর্ঘটনাক্রমে নীড়ের সমাধান করে। তবে হ্যাঁ, আপনি এটি দুটি উপায়েই পেতে পারেন।
ড্যান আব্রামভ

4
আমার অভিজ্ঞতায় আমি বলব: যদি মডেল কোনও স্থানীয় উপাদানগুলির সাথে সম্পর্কিত হয় (যেমন একটি মোছার কনফার্মেশন মডেল মুছুন বোতামের সাথে সম্পর্কিত), তবে এটি পোর্টালটি ব্যবহার করা সহজ, অন্যথায় রিডাক্স ক্রিয়া ব্যবহার করুন। @ কাইলের সাথে একমত যে কোনও একটি মডেল থেকে একটি মডেল খুলতে সক্ষম হবে। এটি পোর্টালগুলির সাথে ডিফল্টরূপেও কাজ করে কারণ তারা বডি ডকুমেন্ট করার জন্য যুক্ত করা হয় যাতে পোর্টালগুলি একে অপরের উপর সুন্দরভাবে স্ট্যাক করে থাকে (যতক্ষণ না আপনি জেড-ইনডেক্সের সাথে সমস্ত কিছু
সেবাস্তিয়ান লোরবার

4
@ ড্যানআব্রামভ, আপনার সমাধানটি দুর্দান্ত, তবে আমার সামান্য সমস্যা আছে। তেমন গুরুত্বপূর্ণ কিছু না. আমি প্রকল্পে ম্যাটারিয়াল-ইউআই ব্যবহার করি, যখন মডেল বন্ধ করার সময় এটি "প্লে" ফিড-অ্যাওম এনিমেশন পরিবর্তে এটি বন্ধ করে দেয়। সম্ভবত কিছুটা বিলম্ব করা দরকার? বা প্রতিটি মডেলকে সেখানে মডালরুটটির তালিকা হিসাবে রাখবেন? পরামর্শ?
gcerar

7
কখনও কখনও আমি মডেল বন্ধ হয়ে যাওয়ার পরে নির্দিষ্ট ফাংশনগুলি কল করতে চাই (উদাহরণস্বরূপ মডেলের অভ্যন্তরে ইনপুট ক্ষেত্রের মানগুলি সহ ফাংশনগুলি কল করুন)। আমি ক্রিয়া হিসাবে এই ফাংশন পাস করব modalProps। এটি যদিও রাজ্যকে সিরিয়ালযোগ্য করে রাখার নিয়ম লঙ্ঘন করে। আমি কীভাবে এই সমস্যাটি কাটিয়ে উঠতে পারি?
চমনী

98

আপডেট : প্রতিক্রিয়া 16.0 লিঙ্কের মাধ্যমে পোর্টাল চালুReactDOM.createPortal

আপডেট : প্রতিক্রিয়াটির পরবর্তী সংস্করণগুলিতে (ফাইবার: সম্ভবত 16 বা 17) পোর্টালগুলি তৈরি করার একটি পদ্ধতি অন্তর্ভুক্ত থাকবে: ReactDOM.unstable_createPortal() লিঙ্ক


পোর্টাল ব্যবহার করুন

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

একটি পোর্টালের সুবিধা হ'ল পপআপ এবং বোতামটি খুব সহজেই প্রতিক্রিয়া গাছের সাথে খুব সহজেই প্রপস ব্যবহার করে পিতা / সন্তানের যোগাযোগ রাখে: আপনি সহজেই পোর্টালগুলির সাথে অ্যাসিঙ্ক ক্রিয়া পরিচালনা করতে পারেন, বা পিতামাতাকে পোর্টালটি কাস্টমাইজ করতে দিন।

পোর্টাল কী?

একটি পোর্টাল আপনাকে এমন document.bodyকোনও উপাদানটির মধ্যে সরাসরি রেন্ডার করার অনুমতি দেয় যা আপনার প্রতিক্রিয়া গাছটিতে গভীরভাবে বাসা বাঁধে।

ধারণাটি হ'ল উদাহরণস্বরূপ আপনি নিম্নলিখিত প্রতিক্রিয়া গাছের শরীরে রেন্ডার করুন:

<div className="layout">
  <div className="outside-portal">
    <Portal>
      <div className="inside-portal">
        PortalContent
      </div>
    </Portal>
  </div>
</div>

এবং আপনি আউটপুট হিসাবে পেতে:

<body>
  <div class="layout">
    <div class="outside-portal">
    </div>
  </div>
  <div class="inside-portal">
    PortalContent
  </div>
</body>

inside-portalনোড ভিতরে অনুবাদ করা হয়েছে <body>তার স্বাভাবিক, গভীরভাবে-নেস্টেড জায়গা পরিবর্তে।

কখন একটি পোর্টাল ব্যবহার করবেন

আপনার বিদ্যমান প্রতিক্রিয়া উপাদানগুলির শীর্ষে থাকা উচিত এমন উপাদানগুলি প্রদর্শন করার জন্য একটি পোর্টাল বিশেষভাবে সহায়ক: পপআপস, ড্রপডাউন, পরামর্শ, হটস্পট

কেন একটি পোর্টাল ব্যবহার

আর জেড-ইনডেক্স সমস্যা নেই : একটি পোর্টাল আপনাকে রেন্ডার করার অনুমতি দেয় <body>। আপনি যদি পপআপ বা ড্রপডাউন প্রদর্শন করতে চান তবে জেড-ইনডেক্স সমস্যার বিরুদ্ধে লড়াই করতে না চাইলে এটি একটি দুর্দান্ত ধারণা। পোর্টাল উপাদানগুলি document.bodyমাউন্ট ক্রমের সাথে যুক্ত হয়ে যায় যার অর্থ আপনি না খেললে z-indexডিফল্ট আচরণটি মাউন্টিং অর্ডারে একে অপরের উপরে পোর্টালগুলি স্ট্যাক করা হবে। অনুশীলনে, এর অর্থ হ'ল আপনি অন্য পপআপের ভিতরে থেকে নিরাপদে একটি পপআপ খুলতে পারবেন এবং নিশ্চিত হয়েও যে দ্বিতীয় পপআপ প্রথমটির উপরে প্রদর্শিত হবে z-index

প্রস্তুতিতে

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

class DeleteButton extends React.Component {
  static propTypes = {
    onDelete: PropTypes.func.isRequired,
  };

  state = { confirmationPopup: false };

  open = () => {
    this.setState({ confirmationPopup: true });
  };

  close = () => {
    this.setState({ confirmationPopup: false });
  };

  render() {
    return (
      <div className="delete-button">
        <div onClick={() => this.open()}>Delete</div>
        {this.state.confirmationPopup && (
          <Portal>
            <DeleteConfirmationPopup
              onCancel={() => this.close()}
              onConfirm={() => {
                this.close();
                this.props.onDelete();
              }}
            />
          </Portal>
        )}
      </div>
    );
  }
}

সরল: আপনি এখনও রেডাক্স রাষ্ট্রটি ব্যবহার করতে পারেন: আপনি যদি সত্যিই চান তবে আপনি এখনও প্রদর্শিত বা না প্রদর্শিত হবে connectতা বেছে নিতে ব্যবহার করতে পারেন DeleteConfirmationPopup। যেহেতু পোর্টালটি আপনার প্রতিক্রিয়া গাছটিতে গভীরভাবে বাসা বেঁধেছে, তাই এই পোর্টালের আচরণটি কাস্টমাইজ করা খুব সহজ কারণ আপনার পিতা-মাতা পোর্টালে প্রপসগুলি দিতে পারেন। আপনি যদি পোর্টাল ব্যবহার না করেন তবে সাধারণত আপনার প্রতিক্রিয়া গাছের শীর্ষে আপনার পপআপগুলি রেন্ডার করতে হবেz-indexকারণগুলি এবং সাধারণত "আমি কীভাবে ব্যবহারের কেস অনুসারে তৈরি জেনেরিক ডিলিট কনফার্মেশনপপআপটি কাস্টমাইজ করব" এর মতো জিনিসগুলি নিয়ে ভাবতে হবে। এবং সাধারণত আপনি এই সমস্যার বেশ কড়া সমাধান পাবেন যেমন নেস্টেড কনফারেন্স / ক্যান্সেল ক্রিয়া, একটি অনুবাদ বান্ডেল কী, বা আরও খারাপ, একটি রেন্ডার ফাংশন (বা অন্য কিছুকে অনিবার্যযোগ্য) রয়েছে এমন কোনও ক্রিয়া প্রেরণের মতো। আপনার পোর্টালগুলির সাথে এটি করার দরকার নেই, এবং কেবল নিয়মিত প্রপসগুলি পাস করতে পারেন, যেহেতু DeleteConfirmationPopupকেবলমাত্র একটি শিশুDeleteButton

উপসংহার

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

নোট করুন যে পোর্টাল বাস্তবায়নগুলি আপনাকে অন্যান্য দরকারী বৈশিষ্ট্যগুলিতে যেমন সহায়তা করতে পারে:

  • অভিগম্যতা
  • পোর্টালটি বন্ধ করার জন্য এস্পেস শর্টকাট
  • বাইরের ক্লিক হ্যান্ডেল করুন (পোর্টালটি বন্ধ করুন বা না)
  • লিঙ্ক ক্লিক হ্যান্ডেল (পোর্টাল বন্ধ বা না)
  • প্রতিক্রিয়া প্রসঙ্গে পোর্টাল ট্রি এ উপলব্ধ করা হয়েছে

প্রতিক্রিয়া-পোর্টাল বা প্রতিক্রিয়া- মডেল পপআপ, মডেল এবং ওভারলেগুলির জন্য দুর্দান্ত যা সাধারণত পর্দার মাঝখানে কেন্দ্রীভূত হয় full

রিএ্যাক্ট -টিথারটি বেশিরভাগ প্রতিক্রিয়া বিকাশকারীদের কাছে অজানা, তবুও এটি আপনি সন্ধান করতে পারেন এমন সবচেয়ে দরকারী সরঞ্জামগুলির মধ্যে একটি। টিথর আপনাকে পোর্টাল তৈরি করার অনুমতি দেয় তবে প্রদত্ত টার্গেটের সাথে সম্পর্কিত পোর্টালটি স্বয়ংক্রিয়ভাবে অবস্থান করবে। এটি টুলটিপস, ড্রপডাউন, হটস্পটস, হেল্পবাক্সগুলির জন্য উপযুক্ত ... আপনার যদি পজিশন absolute/ relativeএবং z-index, এবং আপনার ড্রপডাউনটি আপনার ভিউপোর্টের বাইরে গিয়ে কোনও সমস্যা হয়ে থাকে তবে টেথার আপনার জন্য সমস্ত কিছু সমাধান করবে।

উদাহরণস্বরূপ, আপনি সহজেই চালিত হটস্পটগুলিতে সহজেই প্রয়োগ করতে পারেন, যা একবার ক্লিক করলে একটি সরঞ্জামদণ্ডে প্রসারিত হয়:

হটস্পট অনবোর্ডিং

বাস্তব উত্পাদন কোড এখানে। কোন সহজ হতে পারে না :)

<MenuHotspots.contacts>
  <ContactButton/>
</MenuHotspots.contacts>

সম্পাদনা করুন : সন্ধান করা রি্যাক্ট-গেটওয়ে যা আপনার পছন্দের নোডে পোর্টালগুলি রেন্ডার করার অনুমতি দেয় (অগত্যা দেহ নয়)

সম্পাদনা : দেখে মনে হচ্ছে রিএ্যাক্ট-পপারটি রিচার-টিচারের জন্য একটি শালীন বিকল্প হতে পারে। পপারজেএসএস একটি লাইব্রেরি যা কেবলমাত্র ডিওএম- কে স্পর্শ না করেই কোনও উপাদানের জন্য উপযুক্ত অবস্থানের সংজ্ঞা দেয়, ব্যবহারকারীকে কোথায় এবং কখন ডম নোড রাখতে চান তা বেছে নিতে দেয়, যখন টেথার সরাসরি দেহের সাথে সংযোজন করে।

সম্পাদনা করুন : প্রতিক্রিয়া-স্লট-ফিলও রয়েছে যা আকর্ষণীয় এবং আপনার গাছের যে কোনও জায়গায় আপনি যে কোনও জায়গায় রাখুন এমন একটি সংরক্ষিত উপাদান স্লটে একটি উপাদান সরবরাহ করার অনুমতি দিয়ে অনুরূপ সমস্যা সমাধানে সহায়তা করতে পারে


উদাহরণস্বরূপ স্নিপেটে নিশ্চিতকরণের পপআপ বন্ধ হবে না যদি আপনি ক্রিয়াটি নিশ্চিত করেন (আপনি যখন বাতিল ক্লিক করবেন তখন বিরোধিতা করবেন)
dKab

কোড স্নিপেটে আপনার পোর্টাল আমদানি অন্তর্ভুক্ত করা সহায়ক হবে। কোন গ্রন্থাগার <Portal>থেকে আসে? আমি অনুমান করছি এটি প্রতিক্রিয়া-পোর্টাল, তবে এটি নিশ্চিত করে জেনে ভাল লাগবে।
পাথর

1
@ এসকিপেক্সগুলি দয়া করে আমার প্রয়োগগুলি সিউডো কোড হিসাবে বিবেচনা করুন। আমি এটি কোনও কংক্রিট লাইব্রেরির বিরুদ্ধে পরীক্ষা করিনি। আমি কেবল এখানে ধারণাটি শেখানোর চেষ্টা করছি একটি কংক্রিট বাস্তবায়ন নয়। আমি উপরের প্রতিক্রিয়া ব্যবহার করতে ব্যবহৃত এবং কোডটি এর সাথে ভাল কাজ করা উচিত, তবে এটি প্রায় কোনও অনুরূপ lib দিয়ে সূক্ষ্মভাবে কাজ করা উচিত।
সেবাস্তিয়ান লরবার

প্রতিক্রিয়া-গেটওয়ে দুর্দান্ত! এটি সার্ভার সাইড রেন্ডারিং সমর্থন করে :)
সাইরিলিউস

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

9

বিষয়টিতে জেএস সম্প্রদায়ের পরিচিত বিশেষজ্ঞদের অনেক ভাল সমাধান এবং মূল্যবান মন্তব্য পাওয়া যাবে found এটি এমন একটি সূচক হতে পারে যা এটি তুচ্ছ সমস্যা হিসাবে দেখা যায় না। আমি মনে করি এ কারণেই এ বিষয়টি নিয়ে সন্দেহ এবং অনিশ্চয়তার উত্স হতে পারে।

এখানে মৌলিক সমস্যাটি হ'ল প্রতিক্রিয়াতে আপনাকে কেবলমাত্র তার পিতামাতার সাথে উপাদানটি মাউন্ট করার অনুমতি দেওয়া হয়েছে যা সর্বদা পছন্দসই আচরণ নয়। তবে কীভাবে এই সমস্যাটির সমাধান করবেন?

আমি সমাধানটি প্রস্তাব করছি, এই সমস্যাটির সমাধানের জন্য সম্বোধন করা। আরও বিস্তারিত সমস্যার সংজ্ঞা, এসসিআর এবং উদাহরণগুলি এখানে পাওয়া যাবে: https://github.com/fckt/react-layer-stack#rationale

যুক্তিসহ ব্যাখ্যা

react/ react-domআসে 2 বেসিক অনুমান / ধারণা নিয়ে আসে:

  • প্রতিটি UI স্বাভাবিকভাবেই শ্রেণিবদ্ধ। componentsএকে অপরকে কীভাবে জড়িয়ে রাখবেন সে সম্পর্কে আমাদের ধারণা রয়েছে
  • react-dom ডিফল্টরূপে তার পিতামাতার ডিওএম নোডে শিশু উপাদানটি (শারীরিকভাবে) মাউন্ট করে

সমস্যাটি হ'ল কখনও কখনও দ্বিতীয় সম্পত্তি আপনার ক্ষেত্রে যা চান তা তা নয়। কখনও কখনও আপনি নিজের উপাদানটি বিভিন্ন শারীরিক ডিওএম নোডে মাউন্ট করতে এবং একই সময়ে পিতা বা মাতার মধ্যে যৌক্তিক সংযোগ রাখতে চান।

ক্যানোনিকাল উদাহরণটি হ'ল টুলটিপ-এর মতো উপাদান: বিকাশের প্রক্রিয়াটির এক পর্যায়ে আপনি দেখতে পেলেন UI elementযে আপনার জন্য আপনার কিছু বিবরণ যুক্ত করতে হবে : এটি স্থির স্তরে রেন্ডার হবে এবং এর স্থানাঙ্কগুলি (যা সেই স্থানাঙ্ক UI elementবা মাউস সমন্বয়গুলি) এবং এটিতে জানতে হবে একই মুহূর্তে এটি এখনই প্রদর্শিত হবে কিনা তা তথ্য প্রয়োজন, এর সামগ্রী এবং অভিভাবক উপাদানগুলির কিছু প্রসঙ্গ। এই উদাহরণটি দেখায় যে কখনও কখনও যৌক্তিক শ্রেণিবিন্যাস শারীরিক DOM শ্রেণিবিন্যাসের সাথে মেলে না।

Https://github.com/fckt/react-layer-stack/blob/master/README.md#real-world-usage-example একবার দেখুন যা আপনার প্রশ্নের উত্তর যা ঠিক আছে তা দেখতে:

import { Layer, LayerContext } from 'react-layer-stack'
// ... for each `object` in array of `objects`
  const modalId = 'DeleteObjectConfirmation' + objects[rowIndex].id
  return (
    <Cell {...props}>
        // the layer definition. The content will show up in the LayerStackMountPoint when `show(modalId)` be fired in LayerContext
        <Layer use={[objects[rowIndex], rowIndex]} id={modalId}> {({
            hideMe, // alias for `hide(modalId)`
            index } // useful to know to set zIndex, for example
            , e) => // access to the arguments (click event data in this example)
          <Modal onClick={ hideMe } zIndex={(index + 1) * 1000}>
            <ConfirmationDialog
              title={ 'Delete' }
              message={ "You're about to delete to " + '"' + objects[rowIndex].name + '"' }
              confirmButton={ <Button type="primary">DELETE</Button> }
              onConfirm={ this.handleDeleteObject.bind(this, objects[rowIndex].name, hideMe) } // hide after confirmation
              close={ hideMe } />
          </Modal> }
        </Layer>

        // this is the toggle for Layer with `id === modalId` can be defined everywhere in the components tree
        <LayerContext id={ modalId }> {({showMe}) => // showMe is alias for `show(modalId)`
          <div style={styles.iconOverlay} onClick={ (e) => showMe(e) }> // additional arguments can be passed (like event)
            <Icon type="trash" />
          </div> }
        </LayerContext>
    </Cell>)
// ...

2

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

নীচের মোডালকন্টেইনার উপাদানটি সেই প্রয়োজনীয়তাগুলি পাশাপাশি মডেল এবং ট্রিগারটির জন্য রেন্ডার ফাংশনগুলি প্রয়োগ করে, যা মডেলটি খোলার জন্য কলব্যাক সম্পাদন করার জন্য দায়বদ্ধ।

import React from 'react';
import PropTypes from 'prop-types';
import Portal from 'react-portal';

class ModalContainer extends React.Component {
  state = {
    isOpen: false,
  };

  openModal = () => {
    this.setState(() => ({ isOpen: true }));
  }

  closeModal = () => {
    this.setState(() => ({ isOpen: false }));
  }

  renderModal() {
    return (
      this.props.renderModal({
        isOpen: this.state.isOpen,
        closeModal: this.closeModal,
      })
    );
  }

  renderTrigger() {
     return (
       this.props.renderTrigger({
         openModal: this.openModal
       })
     )
  }

  render() {
    return (
      <React.Fragment>
        <Portal>
          {this.renderModal()}
        </Portal>
        {this.renderTrigger()}
      </React.Fragment>
    );
  }
}

ModalContainer.propTypes = {
  renderModal: PropTypes.func.isRequired,
  renderTrigger: PropTypes.func.isRequired,
};

export default ModalContainer;

এবং এখানে একটি সাধারণ ব্যবহারের কেস ...

import React from 'react';
import Modal from 'react-modal';
import Fade from 'components/Animations/Fade';
import ModalContainer from 'components/ModalContainer';

const SimpleModal = ({ isOpen, closeModal }) => (
  <Fade visible={isOpen}> // example use case with animation components
    <Modal>
      <Button onClick={closeModal}>
        close modal
      </Button>
    </Modal>
  </Fade>
);

const SimpleModalButton = ({ openModal }) => (
  <button onClick={openModal}>
    open modal
  </button>
);

const SimpleButtonWithModal = () => (
   <ModalContainer
     renderModal={props => <SimpleModal {...props} />}
     renderTrigger={props => <SimpleModalButton {...props} />}
   />
);

export default SimpleButtonWithModal;

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

আপনি যদি ট্রিগার উপাদান থেকে মোডাল উপাদানটিতে গতিশীল প্রপস প্রেরণ করতে চান যা আশাকরি খুব বেশি ঘটে না, আমি মোডালকন্টেইনারকে একটি ধারক উপাদান দিয়ে মোড়ানোর পরামর্শ দিচ্ছি যা ডাইনামিক প্রপসকে তার নিজের অবস্থায় পরিচালনা করে এবং মূল রেন্ডার পদ্ধতিগুলি বাড়ায় তাই।

import React from 'react'
import partialRight from 'lodash/partialRight';
import ModalContainer from 'components/ModalContainer';

class ErrorModalContainer extends React.Component {
  state = { message: '' }

  onError = (message, callback) => {
    this.setState(
      () => ({ message }),
      () => callback && callback()
    );
  }

  renderModal = (props) => (
    this.props.renderModal({
       ...props,
       message: this.state.message,
    })
  )

  renderTrigger = (props) => (
    this.props.renderTrigger({
      openModal: partialRight(this.onError, props.openModal)
    })
  )

  render() {
    return (
      <ModalContainer
        renderModal={this.renderModal}
        renderTrigger={this.renderTrigger}
      />
    )
  }
}

ErrorModalContainer.propTypes = (
  ModalContainer.propTypes
);

export default ErrorModalContainer;

0

কোনও সংযুক্ত পাত্রে মডেলটি মোড়ুন এবং এখানে এসিঙ্ক অপারেশন করুন perform আপনি ক্রিয়াকলাপ এবং অনক্লোজ প্রোপ উভয় প্রেরণে পৌঁছাতে পারেন। dispatchপ্রপস থেকে পৌঁছতে , এতে ফাংশনটি পাস করবেন নাmapDispatchToPropsconnect

class ModalContainer extends React.Component {
  handleDelete = () => {
    const { dispatch, onClose } = this.props;
    dispatch({type: 'DELETE_POST'});

    someAsyncOperation().then(() => {
      dispatch({type: 'DELETE_POST_SUCCESS'});
      onClose();
    })
  }

  render() {
    const { onClose } = this.props;
    return <Modal onClose={onClose} onSubmit={this.handleDelete} />
  }
}

export default connect(/* no map dispatch to props here! */)(ModalContainer);

অ্যাপটি যেখানে মডেলটি রেন্ডার করা হয় এবং এর দৃশ্যমান অবস্থা সেট করা থাকে:

class App extends React.Component {
  state = {
    isModalOpen: false
  }

  handleModalClose = () => this.setState({ isModalOpen: false });

  ...

  render(){
    return (
      ...
      <ModalContainer onClose={this.handleModalClose} />  
      ...
    )
  }

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