我有一个关于将值(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,
});
}
}
答案 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
。