我发现了一个让我头疼的问题,我目前正在使用反应dan redux来处理CRUD UI。
一切正常,直到我发现我的“编辑页面”不能正常工作,我发现在将我的全局状态从reducer映射到本地组件道具后,显然组件根本没有更新或重新渲染。以下是我的javascript示例:index.js:
import React from "react";
import ReactDOM from "react-dom";
import {Router, Route, IndexRoute, hashHistory} from "react-router";
import {Provider} from "react-redux";
import store from "./store/store";
import Department from "./components/pages/department/index";
import DepartmentAdd from "./components/pages/department/add";
import DepartmentEdit from "./components/pages/department/edit";
const app = document.getElementById("app");
ReactDOM.render(
<Provider store={store}>
<Router history={hashHistory}>
<Route path="/" component={Layout} onEnter={requireLogin}>
<IndexRoute component={Dashboard} onEnter={requireLogin}/>
<Route path="error404" component={ERROR404}/>
<Route path="department" onEnter={requireLogin}>
<IndexRoute component={Department}/>
<Route path="add" component={DepartmentAdd}/>
<Route path="edit/:id" component={DepartmentEdit}/>
</Route>
</Route>
</Router>
</Provider>
, app);
departmentReducer.js
export default function (state = {
message: null,
activeRow: {},
error: false
}, action) {
switch (action.type) {
case "GET_SINGLE_DEPARTMENT": {
state = {
...state,
activeRow: {...action.payload.data},
message: action.payload.success.message,
error: false
};
break;
}
case "GET_SINGLE_DEPARTMENT_FAILED": {
state = {...state, message: action.payload.error.message, error: true};
break;
}
default: {
state = {...state};
break;
}
}
return state;
}
store.js
import {createStore, applyMiddleware} from "redux";
import thunk from "redux-thunk";
import {createLogger} from "redux-logger";
import promise from "redux-promise-middleware";
import {composeWithDevTools} from "redux-devtools-extension";
import persistState from 'redux-localstorage';
import combineReducer from "./../reducers/combineReducer";
const middleware = composeWithDevTools(applyMiddleware(promise(), thunk, createLogger()), persistState());
export default createStore(combineReducer, middleware);
combineReducer.js
import {combineReducers} from "redux";
import departmentReducer from "./departmentReducer";
export default combineReducers({
departmentReducer
});
departmentActions.js
import axios from "axios";
export function getSingleDepartment(id = 0) {
return function (dispatch) {
axios.get('department/show/' + id).then((response) => {
dispatch({type: "GET_SINGLE_DEPARTMENT", payload: response.data})
}).catch((error) => {
dispatch({type: "GET_SINGLE_DEPARTMENT_FAILED", payload: error.response.data})
})
}
}
最后是edit.js
import React from "react";
import ContentHeader from "./../shared/ContentHeader";
import {connect} from "react-redux";
import {hashHistory} from "react-router";
import {getSingleDepartment} from "./../../../actions/departmentActions";
import ErrorAlert from "./../shared/ErrorAlert";
import SuccessAlert from "./../shared/SuccessAlert";
@connect((store) => {
return {
activeRow: store.departmentReducer.activeRow,
error: store.departmentReducer.error,
message: store.departmentReducer.error,
}
})
export default class index extends React.Component {
constructor() {
super();
this.state
}
componentDidMount() {
this.props.dispatch(getSingleDepartment(this.props.params.id));
}
render() {
const {namaDepartment, deskripsiDepartment} = this.props.activeRow;
return (
<section>
<ContentHeader title="Edit Department"/>
<div class="body">
<div class="bodyWrapper col-lg-12 col-md-12 col-sm-12 col-xs-12">
<ErrorAlert error={this.props.error} message={this.props.message}/>
<SuccessAlert error={this.props.error} message={this.props.message}/>
<form onSubmit={this.saveProfile.bind(this)}>
<div className="half col-lg-6 col-md-6 col-sm-12 col-xs-12">
<div className="feWrapper">
<label for="nama">Nama Department</label>
<input defaultValue={namaDepartment}
type="text"
ref="nama"
id="nama"
name="nama"
className="form-control"/>
</div>
<div className="feWrapper">
<label for="nama">Deskripsi Department</label>
<textarea defaultValue={deskripsiDepartment}
type="text"
ref="deskripsi"
id="deskripsi"
name="deskripsi"
className="form-control"/>
</div>
<div className="feWrapper">
<ul className="myBtnGroup">
<li>
<input onClick={this.onReturnToMain.bind(this)} type="button"
value="kembali"
className="btn btn-info"/>
</li>
<li>
<input onClick={this.cancelSave.bind(this)} type="button" value="batal"
className="btn btn-primary"/>
</li>
<li>
<input type="submit" value="ubah" className="btn btn-info"/>
</li>
</ul>
</div>
</div>
<div className="clearfix"></div>
</form>
</div>
<div class="clearBoth"></div>
</div>
</section>
);
}
}
这是我在浏览器中运行时的样子:
文本框内的值是先前状态的值,虽然状态正在更新,但在刷新页面之前组件不会重新呈现。
所以请任何人帮助我吗?请帮助我..
问候,
Vidy Hermes
答案 0 :(得分:1)
只需从输入组件中删除defaultValue
即可。
defaultValue
将它们变成不受控制的组件。
https://facebook.github.io/react/docs/uncontrolled-components.html#default-values
如果您想更新组件值:
<input
type="text"
ref="nama"
id="nama"
name="nama"
className="form-control"
value={namaDepartment}
/>
<textarea
type="text"
ref="deskripsi"
id="deskripsi"
name="deskripsi"
className="form-control"
value={deskripsiDepartment}
/>
答案 1 :(得分:0)
我不确定是不是这样,但我看到两件可能相关的事情(评论太长了,所以如果它不是解决方案,我会编辑/删除这个答案):
在reducer中,不要改变状态对象,而只是在每个apply plugin: 'com.android.application'
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
android {
compileSdkVersion 26
buildToolsVersion '25.0.3'
defaultConfig {
applicationId "com.credihealth.android"
minSdkVersion 16
targetSdkVersion 26
versionCode 52
versionName "4.2.1.1"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
productFlavors {
demo {
applicationIdSuffix ".demo"
}
full {
applicationIdSuffix ".full"
}
}
}
repositories {
mavenCentral()
flatDir {
dirs 'libs'
}
}
dependencies {
compile(name: "youtube_player_api", ext: "jar")
// this line must be included to integrate with Firebase
// this line must be included to use FCM
compile 'com.android.support:appcompat-v7:26.0.1'
compile 'com.android.support:design:26.0.1'
compile 'com.android.support:recyclerview-v7:26.0.1'
compile 'com.android.support:palette-v7:26.0.1'
compile 'com.android.support:cardview-v7:26.0.1'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
compile 'com.roomorama:caldroid:2.2.1'
compile 'com.facebook.android:facebook-android-sdk:4.7.0'
compile 'com.uncopt:android.justified:1.0'
compile 'com.yayandroid:LocationManager:2.0.3'
compile 'com.google.android.gms:play-services-plus:11.0.1'
compile 'com.google.android.gms:play-services-location:11.0.1'
compile 'com.google.android.gms:play-services-auth:11.0.1'
compile 'com.google.android.gms:play-services-analytics:11.0.1'
compile 'com.google.android.gms:play-services-maps:11.0.1'
compile 'com.hbb20:ccp:1.7.6'
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
compile 'com.github.aakira:expandable-layout:1.6.0@aar'
compile 'com.google.firebase:firebase-core:11.0.1'
compile 'com.google.firebase:firebase-messaging:11.0.1'
compile 'com.stepstone.stepper:material-stepper:3.3.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
fullCompile 'com.twilio:video-android:1.3.0'
}
apply plugin: 'com.google.gms.google-services'
块上返回一个新对象:
case
另外,没有必要在export default function (state = {
message: null,
activeRow: {},
error: false
}, action) {
switch (action.type) {
case "GET_SINGLE_DEPARTMENT": {
return {
...state,
activeRow: {...action.payload.data},
message: action.payload.success.message,
error: false
};
}
case "GET_SINGLE_DEPARTMENT_FAILED": {
return {...state, message: action.payload.error.message, error: true};
}
default:
return state;
}
}
中写下这行代码:
constructor
我几乎可以肯定它与您的问题无关,但如果您没有填充this.state
,那么这不应该存在;