আমি কি রিডিউসারে কোনও ক্রিয়া প্রেরণ করতে পারি?


195

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

//reducer

const initialState = {
    audioElement: new AudioElement('test.mp3'),
    progress: 0.0
}

initialState.audioElement.audio.ontimeupdate = () => {
    console.log('progress', initialState.audioElement.currentTime/initialState.audioElement.duration);
    //how to dispatch 'SET_PROGRESS_VALUE' now?
};


const audio = (state=initialState, action) => {
    switch(action.type){
        case 'SET_PROGRESS_VALUE':
            return Object.assign({}, state, {progress: action.progress});
        default: return state;
    }

}

export default audio;

কী AudioElement? দেখে মনে হচ্ছে এটি রাজ্যে কিছু হওয়া উচিত নয়।
ebuat3989

এটি একটি ES6 সমতল শ্রেণি (কোনও প্রতিক্রিয়া নয়), একটি অডিও অবজেক্ট ধারণ করে। এটি যদি রাজ্যে না থাকে তবে আমি কীভাবে প্লে / স্টপ, স্কিপিং ইত্যাদি নিয়ন্ত্রণ করব?
ক্লানাম

2
আপনি
রিডেক্স

উত্তর:


150

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

আপনার প্রারম্ভিক AudioElementশ্রেণীর মতো শব্দ এবং ইভেন্ট শ্রোতা রাষ্ট্রের পরিবর্তে কোনও উপাদানগুলির মধ্যে অন্তর্ভুক্ত। ইভেন্ট শ্রোতার মধ্যে আপনি একটি ক্রিয়া প্রেরণ করতে পারেন, যা progressরাষ্ট্র আপডেট হবে ।

আপনি হয় AudioElementনতুন প্রতিক্রিয়া উপাদানটিতে শ্রেণি অবজেক্টটি আরম্ভ করতে পারেন বা কেবল শ্রেণিটিকে একটি প্রতিক্রিয়া উপাদানে রূপান্তর করতে পারেন।

class MyAudioPlayer extends React.Component {
  constructor(props) {
    super(props);

    this.player = new AudioElement('test.mp3');

    this.player.audio.ontimeupdate = this.updateProgress;
  }

  updateProgress () {
    // Dispatch action to reducer with updated progress.
    // You might want to actually send the current time and do the
    // calculation from within the reducer.
    this.props.updateProgressAction();
  }

  render () {
    // Render the audio player controls, progress bar, whatever else
    return <p>Progress: {this.props.progress}</p>;
  }
}

class MyContainer extends React.Component {
   render() {
     return <MyAudioPlayer updateProgress={this.props.updateProgress} />
   }
}

function mapStateToProps (state) { return {}; }

return connect(mapStateToProps, {
  updateProgressAction
})(MyContainer);

নোট করুন যে এটি updateProgressActionস্বয়ংক্রিয়ভাবে মোড়ানো হয়েছে dispatchযাতে আপনার সরাসরি প্রেরণ কল করার প্রয়োজন হয় না।


স্পষ্টির জন্য আপনাকে অনেক ধন্যবাদ! তবে আমি কীভাবে প্রেরককে অ্যাক্সেস করতে পারি তা জানি না। আমি সবসময় প্রতিক্রিয়া-হ্রাস থেকে সংযোগ পদ্ধতিটি ব্যবহার করি। তবে আপডেট আপডেট পদ্ধতিতে কীভাবে এটি কল করা যায় তা আমি জানি না। বা প্রেরণকারী পেতে অন্য উপায় আছে। প্রপস সঙ্গে হতে পারে? আপনাকে ধন্যবাদ
ক্লানাম

সমস্যা নেই. আপনি সম্পাদিত MyAudioPlayerমূল পাত্রে থেকে উপাদানটিতে ক্রিয়াকলাপটি দিতে পারেন । এখানে এটি কীভাবে করবেন তা দেখুন : github.com/reactjs/react-redux/blob/master/docs/…connectreact-reduxmapDispatchToProps
ebuat3989

6
updateProgressActionআপনার উদাহরণে প্রতীকটি কোথায় সংজ্ঞায়িত করা হয়েছে?
চার্লস প্রকাশ দাশারি

2
আপনি যদি কোনও হ্রাসকারকের মধ্যে কোনও ক্রিয়া প্রেরণ করার কথা না মনে করেন, তবে হু হু হু হুইট রিডাক্সের নিয়ম ভঙ্গ করছেন?
এরিক উইনার

2
@ এরিকওয়েনার আমার বিশ্বাস redux-thunk, অন্য কোনও ক্রিয়াকলাপ থেকে কোনও পদক্ষেপ প্রেরণ করা হচ্ছে, হ্রাসকারীকে নয়। stackoverflow.com/questions/35411423/...
sallf

158

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

এখানে একটি মিডওয়্যার রয়েছে যা asyncDispatchআপনার সমস্ত ক্রিয়ায় সম্পত্তি যুক্ত করবে । আপনার হ্রাসকারক শেষ নতুন অ্যাপ্লিকেশন রাষ্ট্র ফিরে এসেছে, তখন asyncDispatchআরম্ভ হবে store.dispatchসঙ্গে যাই হোক না কেন কর্ম আপনি এটি দেব।

// This middleware will just add the property "async dispatch"
// to actions with the "async" propperty set to true
const asyncDispatchMiddleware = store => next => action => {
  let syncActivityFinished = false;
  let actionQueue = [];

  function flushQueue() {
    actionQueue.forEach(a => store.dispatch(a)); // flush queue
    actionQueue = [];
  }

  function asyncDispatch(asyncAction) {
    actionQueue = actionQueue.concat([asyncAction]);

    if (syncActivityFinished) {
      flushQueue();
    }
  }

  const actionWithAsyncDispatch =
    Object.assign({}, action, { asyncDispatch });

  const res = next(actionWithAsyncDispatch);

  syncActivityFinished = true;
  flushQueue();

  return res;
};

এখন আপনার হ্রাসকারী এটি করতে পারেন:

function reducer(state, action) {
  switch (action.type) {
    case "fetch-start":
      fetch('wwww.example.com')
        .then(r => r.json())
        .then(r => action.asyncDispatch({ type: "fetch-response", value: r }))
      return state;

    case "fetch-response":
      return Object.assign({}, state, { whatever: action.value });;
  }
}

7
মার্সেলো, আপনার ব্লগ পোস্টটি এখানে আপনার পদ্ধতির পরিস্থিতি বর্ণনা করে একটি দুর্দান্ত কাজ করেছে, তাই আমি এখানে এটি যুক্ত করছি: lazamar.github.io/dispatching-from-inside-of-reducers
দেজে ক্লেটন

3
মিডলওয়্যার যেমনটি হয় ঠিক তেমন বিরতি dispatchযা আমার ক্রিয়াকলাপটি ফিরিয়ে দেবে , ব্যতীত এটিই আমার প্রয়োজন ছিল । আমি শেষ লাইনগুলিতে পরিবর্তন করেছি: const res = next(actionWithAsyncDispatch); syncActivityFinished = true; flushQueue(); return res;এবং এটি দুর্দান্ত কাজ করেছে।
জ্যানারক

1
আপনি যদি কোনও হ্রাসকারকের মধ্যে কোনও ক্রিয়া প্রেরণ করার কথা না মনে করেন, তবে হু হু হু হুইট রিডাক্সের নিয়ম ভঙ্গ করছেন?
এরিক উইনার

আপনি যখন ওয়েবসকেট প্রতিক্রিয়াগুলি হ্যান্ডেল করার চেষ্টা করবেন তখন এটি কীভাবে কাজ করবে? এটি আমার হ্রাসকারক রফতানি ডিফল্ট (রাষ্ট্র, ক্রিয়া) => {কনট এম 2 = [... state.messages, action.payload] রিটার্ন অবজেক্ট.সেসাইন ({}, রাজ্য, {বার্তা: এম 2,}) I এবং আমি এখনও এই ত্রুটিটি পান "রাষ্ট্রের রূপান্তরগুলি প্রেরণের মধ্যে সনাক্ত করা হয়েছিল"
কোয়ান্টাম্পোটাটো

12

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


1
আপনি কীভাবে 'রেডেক্সার-অভ্যন্তরে অন্য প্রেরণের শিডিয়ুলিং' অর্জন করবেন তা নির্দিষ্ট করতে পারেন?
এক্সপিডি

1
@ এক্সপিডি আপনি কী সম্পাদন করতে চান তা আরও একটু ব্যাখ্যা করতে পারেন? আপনি যদি অন্য কোনও ক্রিয়াকলাপ প্রেরণের জন্য কোনও হ্রাসকারী ক্রিয়া ব্যবহার করার চেষ্টা করছেন, আপনি রিডেক্স-সাগা সদৃশ কিছু ছাড়া সক্ষম হবেন না।
chandlervdw

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

1
ঠিক আছে, যাক, supplierযখন আপনি itemবিশদ পৃষ্ঠাটি দেখার চেষ্টা করেন তথ্যের জন্য আপনি এই অনুরোধটি বন্ধ করতে চেয়েছিলেন । তোমার componentDidMount()একটি ফাংশন যে একটি কর্ম পাঠাবে বন্ধ করো না, বলতে FETCH_SUPPLIER। হ্রাসকারীর মধ্যে, loading: trueঅনুরোধ করা হওয়ার সময় আপনি কোনও স্পিনার দেখানোর জন্য এমন কিছুতে টিক দিতে পারেন । redux-sagaএই ক্রিয়াটি শুনবে এবং প্রতিক্রিয়া হিসাবে, আসল অনুরোধটি বন্ধ করে দেবে। জেনারেটরের ফাংশনগুলি ব্যবহার করে, এটি তখন প্রতিক্রিয়াটির জন্য অপেক্ষা করতে পারে এবং এতে ডাম্প করতে পারে FETCH_SUPPLIER_SUCCEEDED। হ্রাসকারী সরবরাহকারী তথ্যের সাথে স্টোর আপডেট করে।
chandlervdw

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