(React/Redux) 组件状态未使用 reducer 和 mapStateToProps 更新
(React/Redux) Component State not being update with reducer and mapStateToProps
我的组件状态没有用 Reducer 更新,在 mapStateToProps 中很好地获取 Reducer 状态并出现在道具中,但它不应该更新我的组件的状态以便它重新渲染吗?在 Reducer returning 状态
{...state, rows:news_formated.slice(0,30)}
文档和评论中的 Spread 语法都说这是用于 return 状态新实例而不改变状态本身的方法之一。下面是Action、Reducer的代码和我的部分组件代码。
class CreateGenericTable extends Component {
constructor(props){
super(props);
this.state = { rows:null, columns:null};
}
componentDidMount(){
var token = getCookie('admin_session_token');
servicerequest = this.props.serviceRequest;
this.setState({columns: this.props.columns})
var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
console.log(this.props);
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({ tableList, editComponent }, dispatch);
}
const mapStateToProps = (state,ownProps) => {
console.log('this is state');
//console.log(state);
if(state.tabledata.rows!=null){
debugger;
return { rows: state.tabledata.rows};
}else{
return { rows: null};
}
};
//export default connect(null, mapDispatchToProps)(CreateGenericTable)
const CreateGenericTableRedux = connect(mapStateToProps, mapDispatchToProps)(CreateGenericTable)
动作
import $ from "jquery";//https://redux.js.org/docs/advanced/AsyncActions.html Asynchronous calls need to use thunk of redux.....
//import { connect } from 'react-redux';
export const FETCH_TABLEDATA = 'FETCH_TABLEDATA'
export const EDIT_COMP = 'EDIT_COMP'
export function editComponent(id,View){
return {
type: EDIT_COMP,
payload: {'id':id,'View':View}
}
}
export function tableList(editform,service,token,serviceRequest){
var request = null;
return dispatch => {
$.ajax({
type: "POST",
url: service,
crossDomain: true,
dataType: 'jsonp',
xhrFields: {
withCredentials: true
},
data: {
q: JSON.stringify({
[serviceRequest]:{}
}),
admin_session_token:token,
},
success : (data) => {
request = data;
dispatch({
type: FETCH_TABLEDATA,
payload: {editform: editform,request: request, serviceRequest: serviceRequest }
});
},
error: (xhr, status, err) =>{
////console.log('ups somehting went rong:'.err.toString());
},
});
};
/*
return request.then ({
type: FETCH_TABLEDATA,
payload: {request: request, serviceRequest: serviceRequest, columns: columns}
});
*/
}
减速器
import { FETCH_TABLEDATA } from '../actions/index.js'
//const INITIAL_STATE = {rows:null, columns:[]} //separate the data proprocessing to a function -> https://gist.github.com/abhiaiyer91/aaf6e325cf7fc5fd5ebc70192a1fa170
export default function(state = [], action){ switch(action.type){ case FETCH_TABLEDATA:
var data = action.payload.request[action.payload.serviceRequest];//var data = data['News_get'];
console.log('----state---'); console.log(state);
if(data.length>0){
var news_formated = [];
var listofkeys = Object.keys(data[0]);
for(var new_unformated of data){
var new_formated = [];
//console.log(new_unformated);
for(var key of listofkeys){
//console.log(key);
if(action.payload.editform.indexOf('EditHeader') !== -1 && key.indexOf('language_items') !== -1){
new_formated['image'] = new_unformated[key][0]['image'];
new_formated['link'] = new_unformated[key][0]['link'];
}else{
if(action.payload.editform.indexOf('EditNotification') !== -1){
if(key.indexOf('params') !== -1){
new_formated[key] = new_unformated[key]['message'];
}else{
new_formated[key] = new_unformated[key];
}
}else{
if(key.indexOf('active') !== -1){
if(new_unformated[key].indexOf('1') !== -1){
new_formated[key] = 'Yes';
}else{
new_formated[key] = 'No';
}
}else{
new_formated[key] = new_unformated[key];
}
}
}
}
news_formated.push(new_formated);
}
return {
...state,
rows:news_formated.slice(0,30)
};
}else{
return {
...state,
rows:null
};
}
//{...state, {rows:null, columns:action.payload.columns}}; default: return {
...state,
rows:null
}; } }
componentDidMount
函数仅在第一次渲染时调用,然后组件安装,因此 redux 存储中的任何进一步更新,反映在组件的 props 中不会在您的实现中设置为 state。您需要在 componentWillReceiveProps
函数
中实现相同的逻辑
还要提醒你,拥有一个直接从 props 派生的状态是一种反模式,你应该直接使用 props。
虽然你可以达到你想要的效果
class CreateGenericTable extends Component {
constructor(props){
super(props);
this.state = { rows:null, columns:null};
}
componentDidMount(){
var token = getCookie('admin_session_token');
servicerequest = this.props.serviceRequest;
this.setState({columns: this.props.columns})
var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
console.log(this.props);
}
componentWillReceiveProps(nextProps) {
if(nextProps.columns !== this.props.columns) { // You might need to have a deep comparison here if columns is not immutable or a nested obejct. You can use _.isEqual from lodash in that case
this.setState({columns: nextProps.columns})
}
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({ tableList, editComponent }, dispatch);
}
const mapStateToProps = (state,ownProps) => {
console.log('this is state');
//console.log(state);
if(state.tabledata.rows!=null){
debugger;
return { rows: state.tabledata.rows};
}else{
return { rows: null};
}
};
export default connect(null, mapDispatchToProps)(CreateGenericTable)
我强烈建议您尽可能直接在组件中使用 this.props.columns
,而不是将其保持在状态
我的组件状态没有用 Reducer 更新,在 mapStateToProps 中很好地获取 Reducer 状态并出现在道具中,但它不应该更新我的组件的状态以便它重新渲染吗?在 Reducer returning 状态
{...state, rows:news_formated.slice(0,30)}
文档和评论中的 Spread 语法都说这是用于 return 状态新实例而不改变状态本身的方法之一。下面是Action、Reducer的代码和我的部分组件代码。
class CreateGenericTable extends Component {
constructor(props){
super(props);
this.state = { rows:null, columns:null};
}
componentDidMount(){
var token = getCookie('admin_session_token');
servicerequest = this.props.serviceRequest;
this.setState({columns: this.props.columns})
var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
console.log(this.props);
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({ tableList, editComponent }, dispatch);
}
const mapStateToProps = (state,ownProps) => {
console.log('this is state');
//console.log(state);
if(state.tabledata.rows!=null){
debugger;
return { rows: state.tabledata.rows};
}else{
return { rows: null};
}
};
//export default connect(null, mapDispatchToProps)(CreateGenericTable)
const CreateGenericTableRedux = connect(mapStateToProps, mapDispatchToProps)(CreateGenericTable)
动作
import $ from "jquery";//https://redux.js.org/docs/advanced/AsyncActions.html Asynchronous calls need to use thunk of redux.....
//import { connect } from 'react-redux';
export const FETCH_TABLEDATA = 'FETCH_TABLEDATA'
export const EDIT_COMP = 'EDIT_COMP'
export function editComponent(id,View){
return {
type: EDIT_COMP,
payload: {'id':id,'View':View}
}
}
export function tableList(editform,service,token,serviceRequest){
var request = null;
return dispatch => {
$.ajax({
type: "POST",
url: service,
crossDomain: true,
dataType: 'jsonp',
xhrFields: {
withCredentials: true
},
data: {
q: JSON.stringify({
[serviceRequest]:{}
}),
admin_session_token:token,
},
success : (data) => {
request = data;
dispatch({
type: FETCH_TABLEDATA,
payload: {editform: editform,request: request, serviceRequest: serviceRequest }
});
},
error: (xhr, status, err) =>{
////console.log('ups somehting went rong:'.err.toString());
},
});
};
/*
return request.then ({
type: FETCH_TABLEDATA,
payload: {request: request, serviceRequest: serviceRequest, columns: columns}
});
*/
}
减速器
import { FETCH_TABLEDATA } from '../actions/index.js'
//const INITIAL_STATE = {rows:null, columns:[]} //separate the data proprocessing to a function -> https://gist.github.com/abhiaiyer91/aaf6e325cf7fc5fd5ebc70192a1fa170
export default function(state = [], action){ switch(action.type){ case FETCH_TABLEDATA:
var data = action.payload.request[action.payload.serviceRequest];//var data = data['News_get'];
console.log('----state---'); console.log(state);
if(data.length>0){
var news_formated = [];
var listofkeys = Object.keys(data[0]);
for(var new_unformated of data){
var new_formated = [];
//console.log(new_unformated);
for(var key of listofkeys){
//console.log(key);
if(action.payload.editform.indexOf('EditHeader') !== -1 && key.indexOf('language_items') !== -1){
new_formated['image'] = new_unformated[key][0]['image'];
new_formated['link'] = new_unformated[key][0]['link'];
}else{
if(action.payload.editform.indexOf('EditNotification') !== -1){
if(key.indexOf('params') !== -1){
new_formated[key] = new_unformated[key]['message'];
}else{
new_formated[key] = new_unformated[key];
}
}else{
if(key.indexOf('active') !== -1){
if(new_unformated[key].indexOf('1') !== -1){
new_formated[key] = 'Yes';
}else{
new_formated[key] = 'No';
}
}else{
new_formated[key] = new_unformated[key];
}
}
}
}
news_formated.push(new_formated);
}
return {
...state,
rows:news_formated.slice(0,30)
};
}else{
return {
...state,
rows:null
};
}
//{...state, {rows:null, columns:action.payload.columns}}; default: return {
...state,
rows:null
}; } }
componentDidMount
函数仅在第一次渲染时调用,然后组件安装,因此 redux 存储中的任何进一步更新,反映在组件的 props 中不会在您的实现中设置为 state。您需要在 componentWillReceiveProps
函数
还要提醒你,拥有一个直接从 props 派生的状态是一种反模式,你应该直接使用 props。
虽然你可以达到你想要的效果
class CreateGenericTable extends Component {
constructor(props){
super(props);
this.state = { rows:null, columns:null};
}
componentDidMount(){
var token = getCookie('admin_session_token');
servicerequest = this.props.serviceRequest;
this.setState({columns: this.props.columns})
var teste = this.props.tableList(this.props.editform,this.props.service,token,servicerequest,this.props.columns)
console.log(this.props);
}
componentWillReceiveProps(nextProps) {
if(nextProps.columns !== this.props.columns) { // You might need to have a deep comparison here if columns is not immutable or a nested obejct. You can use _.isEqual from lodash in that case
this.setState({columns: nextProps.columns})
}
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({ tableList, editComponent }, dispatch);
}
const mapStateToProps = (state,ownProps) => {
console.log('this is state');
//console.log(state);
if(state.tabledata.rows!=null){
debugger;
return { rows: state.tabledata.rows};
}else{
return { rows: null};
}
};
export default connect(null, mapDispatchToProps)(CreateGenericTable)
我强烈建议您尽可能直接在组件中使用 this.props.columns
,而不是将其保持在状态