Reactjs 在现有状态转换错误期间无法更新

Reactjs 在现有状态转换错误期间无法更新,reactjs,redux,react-redux,react-router-v4,Reactjs,Redux,React Redux,React Router V4,编辑:我解决了我的问题,它现在正在为我工作-还编辑了我的代码以反映新的更改。 我得到了这个错误,我不知道是什么原因造成这个错误 我无法显示代码,因为它是公司的资料,所以我将尽力描述它: App.js: `class App extends React.Component { constructor(props) { super(props); } render () { return ( <div>

编辑:我解决了我的问题,它现在正在为我工作-还编辑了我的代码以反映新的更改。

我得到了这个错误,我不知道是什么原因造成这个错误

我无法显示代码,因为它是公司的资料,所以我将尽力描述它:

App.js:

`class App extends React.Component {
    constructor(props) {
        super(props);
    }

    render () {
        return (
            <div>
                <Header />
                <RouteList />
                <Footer />
            </div>
        )
    }
}`
renderHeader是renderHeaderReducer

headerAction.js

export function changeHeader(headerType) {
    if (headerType == "abc") {
        return {type: type, headerType: "abc"}
    } [...] {
        // something default
    }
}
renderHeaderReducer.js

const rootReducer = combineReducers({renderHeader});
export default rootReducer;
export default function renderHeaderReducer(state = initialState, action) {
switch(action.type) {
    case "abc":
        return (Object.assign({}, ...state, {headerType: action.headerType}));
    [...];
    default:
        return state;
}
}

此时,单击链接时,web浏览器应刷新,保留标题,但修改零件。然而,我的网站进入了一个无限循环,错误是:

错误:无法在现有状态转换期间更新(例如在渲染或其他组件的构造函数中)。渲染方法应该是道具和状态的纯函数;构造函数的副作用是一种反模式,但可以移动到componentWillMount

当我做了一个console.log来查看发生了什么时,它似乎在我定义的所有各种选项上循环,这些选项将呈现Header.js

事实证明,主要问题是我调用onClick方法时出现的。对我的代码进行错误处理的无限循环是onClick函数在未单击的情况下启动的结果

原始:
onClick={this.changeHeader('abc')}
新:
onClick={()=>changeHeader('abc')}

有关说明,请参阅此


谢谢。

是时候来点伪代码了:)

据我所知,您有一个Header组件,它连接到一个rootReducer组件,该组件包含您所在路由器链接的Header

我的应用程序中有一些类似的代码,其中我们使用单个组件分派操作来更新rootReducer头。标头只使用redux侦听更新并重新呈现自身

class Header extends React.Component {
     // render the header 
     render() {...}
 }
 const mapStateToProps = (state) => {
     return {
        header: state.rootReducer.header
     }
 }
 export default withRouter(connect(mapStateToProps, {})(Header));
组件

 class MySpecialRouteComponent extends React.Component {
     componentDidMount() {
         this.props.changeHeader("Special Component")
     }
     render() {...}
 }
 const mapStateToProps = (state) => {
     return {
       ...whatever 
     }
 }
 export default withRouter(connect(mapStateToProps, {changeHeader})(MySpecialRouteComponent));

你不应该让render在React中执行设置状态

我将展示我将如何安排一切来处理这种情况

redux/header actions.js(从组件中调用这些动作创建者):

redux/header reducers.js(注意:这将在调用操作时处理):

redux/index.js

import headerReducers from './reducers/header-reducers';
import { combineReducers } from 'redux';

const allReducers = combineReducers({
    header: headerReducers
});

export default allReducers;
class aHeader {

    constructor() {
        super();
        this.changeHeader = this.changeHeader.bind(this);
    }

    render() {
        return <div onClick={this.changeHeader}>header a</div>;
    }

    changeHeader() {
        this.props.changeHeader('header-b'); // call the action creator here
    }
}
现在,您可以像这样设置header.js组件:

import { changeHeader } from '../redux/header-actions';

class Header extends Component {

    render() {
        return (
            <div>{this.renderHeader()}</div>
        );
    }

    renderHeader() {
        if (this.props.headerType === 'header-a')
            return <aHeader changeHeader={this.props.changeHeader} />
        else
            return <bHeader changeHeader={this.props.changeHeader} />;
    }

}

function mapStateToProps(store, ownProps) {
    return {
        headerType: store.header.headerType
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        changeHeader: changeHeader
    },
    dispatch);
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header));
从“../redux/header actions”导入{changeHeader};
类头扩展组件{
render(){
返回(
{this.renderHeader()}
);
}
renderHeader(){
if(this.props.headerType==='header-a')
返回
其他的
返回;
}
}
函数mapStateToProps(存储、ownProps){
返回{
headerType:store.header.headerType
};
}
功能图DispatchToprops(调度){
返回bindActionCreators({
changeHeader:changeHeader
},
派遣);
}
使用路由器导出默认值(connect(mapStateToProps,mapDispatchToProps)(标头));
然后,例如,aHeader.js

import headerReducers from './reducers/header-reducers';
import { combineReducers } from 'redux';

const allReducers = combineReducers({
    header: headerReducers
});

export default allReducers;
class aHeader {

    constructor() {
        super();
        this.changeHeader = this.changeHeader.bind(this);
    }

    render() {
        return <div onClick={this.changeHeader}>header a</div>;
    }

    changeHeader() {
        this.props.changeHeader('header-b'); // call the action creator here
    }
}
class-aHeader{
构造函数(){
超级();
this.changeHeader=this.changeHeader.bind(this);
}
render(){
返回收割台a;
}
changeHeader(){
this.props.changeHeader('header-b');//在此处调用动作创建者
}
}

您说state.renderHeader是在rootReducer中声明的;但是,您不应该从代码中调用reducer函数。相反,您应该调用actions,这反过来会触发相应的reducer函数来修改您的状态。@sme我调用了action
this.props.actions.changeHeader(headerType)
您是否在任何地方调用
renderHeader
函数?我仍在试图弄清楚这是否会对您的代码产生影响。但是,如果它是一个reducer函数,那么它不应该出现在mapstateTrops()函数中。@sme,我不会在其他任何地方调用我的renderHeader函数。我认为mapStateToProps()函数应该将reducer映射到props?mapStateToProps应该只用于传递redux存储(state)中的属性,或者通过
ownProps
直接传递到组件的属性。动作创建者应该在mapDispatchToProps()中,我在代码中看到的是正确的。调用action creator函数后,它将创建该操作,然后根据该操作包含的
类型
属性自动调用相应的reducer。您不需要手动调用任何缩减器,也不需要将它们传递给任何组件。您可以解释一下为什么将{changeHeader}放在mapDispatchToProps的位置吗?显示的当前头应该保存在Redux存储中。您应该有一个操作创建者,
changeHeader(headerType)
,它将创建一个操作来更改存储中的头类型。然后,reducer将使用传递给action creator的
headerType
更新存储。我在代码中添加了更多显示action和reducers@sme这是对的。changeHeader是一个动作创建者,它分派和更新根还原器中的状态。即使在使用更多代码AKJ进行更新之后,我觉得我的方法更适合渲染头文件,至少在这种情况下是这样。没有苛刻的感觉:)@dixitk13没有冒犯,我真的很想学习成为一名更好的编码员,你和sme都提供了惊人的帮助。你能详细说明你的代码吗?我想看看你是如何组织你的。我正在尝试sme的一个,看看它是否适合我。为什么我不该让render去做?优点和缺点是什么?顺便说一句,AllReducer中有一个输入错误,它必须是headerReducers而不是header reducer。同样对于OP所遵循的这个具体方法,如果明天他的头球中有另一个道具,并且假设每次都会在他的路线中更新,那么他的头球不会经历几次重新渲染吗?因为无论何时发生渲染调用,都会在头c中发生额外的渲染调用
class aHeader {

    constructor() {
        super();
        this.changeHeader = this.changeHeader.bind(this);
    }

    render() {
        return <div onClick={this.changeHeader}>header a</div>;
    }

    changeHeader() {
        this.props.changeHeader('header-b'); // call the action creator here
    }
}