将值从组件传递到其他组件的redux-saga的最佳方法

时间:2018-08-29 08:01:42

标签: reactjs react-redux redux-saga

我有一个关于将值(item.id)从一个组件传递到另一个组件的传奇的问题,我可以在POST正文中添加其他字段并提出请求。

我有两个组件:1st Form组件,其中是两个输入字段。第二个组件是Item,它是从API获取的。因此,有一个itemId值,在使用表单发出POST请求时需要提供该值。

我现在的解决方法是将itemId传递给localstorage,然后将其作为传奇,但是当用户打开两个浏览器窗口时,这会引起一些错误。什么是对此任务更好的解决方案?

我的项目组件:

export class FindClientItem extends React.PureComponent {
  constructor() {
    super();

    this.state = {
      modalIsOpen: false,
    };

    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  openModal() {
    this.setState({ modalIsOpen: true });
  }

  closeModal() {
    this.setState({ modalIsOpen: false });
    localStorage.removeItem('itemId');
  }

  render() {
    const { item } = this.props;

    if(this.state.modalIsOpen){
     localStorage.setItem('itemId',item.itemId);
    }

    // Put together the content of the repository
    const content = (
      <Wrapper>
        <h3>{item.title}</h3>
        Details: {item.description}...<button onClick={this.openModal}>
          More
        </button>
        <Modal
          isOpen={this.state.modalIsOpen}
          onRequestClose={this.closeModal}
          style={customStyles}
          contentLabel="Modal"
        >
          <h3>{item.title}</h3>
          Details: {item.description} <br />
          <button onClick={this.openBidModal}>Submit</button>{' '}
        </Modal>
      </Wrapper>
    );

    // Render the content into a list item
    return <ListItem key={`items-${item.itemId}`} item={content} />;
  }
}

然后是我的其他1st Form组件的传奇:

export function* submitForm() {
  try {
    const formType = 'item';
    const body = yield select(makeSelectModifiedData());
    body.itemId = localStorage.getItem('itemId');
    let requestURL;

    switch (formType) {
      case 'item':
        requestURL = 'http://localhost:1234/item';
        break;
      default:
    }
    const response = yield call(request, requestURL, { method: 'POST', body });
  } catch (error) {
    Alert.error('Error message...', {
      html: false,
    });
  }
}

3 个答案:

答案 0 :(得分:0)

不确定这是否是“最佳”方法,但是对我来说效果很好。您是否尝试过创建一个共享的js文件(导入到两个组件中),而该文件是GETS / SETS一个变量?例如。

shared.js

let data = null;

setData(d){
    data = d;
}

getData(){
    return data;
}

addChangeListner(eventName, callback){
    this.on(eventname, callback);
}

dispatcherCallback(action){
    switch(action.actionType){
         case 'SET_DATA':
         this.getData();
    }
}

无论何时需要更新组件,都可以添加一个更改侦听器,然后在设置好之后返回新数据,这样就不会使组件不同步。只要记住删除听众后记!

组件

componentDidMount(){
    shared.addChangeListner('SET_DATA', this.onUpdate)
}

// use x to pass to your saga...
onUpdate(){
    var x = shared.getData();
}

希望这会有所帮助!

答案 1 :(得分:0)

index.js

import {handleSave, loadData } from './action';
import Modal from './Modal',

export class GetFormData extends React.PureComponent {

  componentDidMount() {
    this.props.loadData();
  }

  saveData = (data) => {
     this.props.handleSave(data)
  }

  render() {
    return (
      <div>

        <Modal
          isOpen={this.state.modalIsOpen}
          onRequestClose={this.closeModal}
          style={customStyles}
          contentLabel="Modal"
          data={this.props.getdata}
         handlePost={this.saveData}
        />
      </div>
    )
  }
}

const mapStateToProps = state => ({
  getdata: state.formData,
});

const mapDispatchToProps = dispatch => ({
  loadData: bindActionCreators(loadData, dispatch),
  handleSave: bindActionCreators(handleSave, dispatch),
});

export default connect(mapStateToProps, mapDispatchToProps)(GetFormData);

actions.js

import {
  LOAD_DATA,
  LOAD_DATA_SUCCESS,
  LOAD_DATA_FAILED
  HANDLE_SAVE,
  HANDLE_SAVE_SUCCESS,
  HANDLE_SAVE_FAILED
} from './constants';

export function loadData() {
  return {
    type: LOAD_DATA,
  };
}

export function loadDataSuccess(formData) {
  return {
    type: LOAD_DATA_SUCCESS,
    formData
  };
}

export function loadDataFailed(error) {
  return {
    type: LOAD_DATA_FAILED,
    error
  };
}

export function handleSave(data) {
  return {
    type: HANDLE_SAVE,
    data
  };
}

export function handleSaveSuccess() {
  return {
    type: HANDLE_SAVE_SUCCESS
  };
}

export function handleSaveFailed(error) {
  return {
    type: HANDLE_SAVE_FAILED,
    error
  };
}

reducers.js

import { fromJS } from 'immutable';

import {
  LOAD_DATA, LOAD_DATA_SUCCESS, LOAD_DATA_FAILED,
  HANDLE_SAVE,
  HANDLE_SAVE_SUCCESS,
  HANDLE_SAVE_FAILED
} from './constants';

const initialState = fromJS({
  formData: undefined,
});


function formDataReducer(state = initialState, action) {
  switch (action.type) {
    case LOAD_DATA:
      return state;

    case LOAD_DATA_SUCCESS:
      return state.set('formData', action.formData);

    case LOAD_DATA_FAILED:
      return state.set('errormsg', fromJS(action.errormsg));

    case HANDLE_SAVE:
      return state.set('data', action.data);

    case HANDLE_SAVE_SUCCESS:
      return state.set('message', action.message);

    case HANDLE_SAVE_FAILED:
      return state.set('errormsg', fromJS(action.errormsg));

    default:
      return state;
  }
}

saga.js

import { takeEvery, call, put } from 'redux-saga/effects';
import {
  LOAD_DATA,
  LOAD_DATA_SUCCESS,
  LOAD_DATA_FAILED,
  HANDLE_SAVE,
  HANDLE_SAVE_SUCCESS,
  HANDLE_SAVE_FAILED
} from './constants';


export function* getFormDataWorker() {
  try {
    const formData = yield call(api);
    if (formData) {
      yield put({ type: LOAD_DATA_SUCCESS, formData });
    }
  } catch (errormsg) {
    yield put({ type: LOAD_DATA_FAILED, errormsg });
  }
}

//  watcher
export function* formDataWatcher() {
  yield takeEvery(LOAD_DATA, getFormDataWorker);
}


export function* saveDataWorker(action) {
  try {
    const message = yield call(savedata, action.data);
    if (message) {
      yield put({ type: HANDLE_SAVE_SUCCESS, message });
    }
  } catch (errormsg) {
    yield put({ type: HANDLE_SAVE_FAILED, errormsg });
  }
}

//  watcher
export function* saveDataWatcher() {
  yield takeEvery(HANDLE_SAVE, saveDataWorker);
}


// All sagas to be loaded
export default [
  saveDataWatcher,
  formDataWatcher,
];

Modal.js

const Modal = ({data, handlePost}) => (
   { data ? data.map(item => (
      <input type="text" value={item.id} />
    )

   }
   <Button type="submit" onClick={handlePost}/ >

)

希望这会有所帮助!

答案 2 :(得分:0)

我建议以下内容:

  • 删除本地存储的使用

  • componentDidUpdate上调度一个在Redux存储中设置itemId的操作。

    componentDidUpdate() { this.props.setItemId({itemId: this.props.item.itemId}) }

  • 在表单提交时,分派与您当前用于触发传奇的动作相同的动作。

  • 更改您的makeSelectModifiedData选择器,以返回您现在存储在Redux中的itemId