gpt4 book ai didi

javascript - 如何避免在 React 中使用 setProps?

转载 作者:可可西里 更新时间:2023-11-01 02:28:29 26 4
gpt4 key购买 nike

我正在使用 react & redux 开发应用程序,我需要 setProps 但它已被弃用。

看看下面的错误:

Warning: setProps(...) and replaceProps(...) are deprecated. Instead, call render again at the top level.

Uncaught Invariant Violation: setProps(...): You called setProps on a component with a parent. This is an anti-pattern since props will get reactively updated when rendered. Instead, change the owner's render method to pass the correct value as props to the component where it is created.

那么我该如何设置 Prop 呢?基本上是管理一些标签,看看下面我的代码:

export default React.createClass({
render: function() {
return (
<div className="demo-tabs">
<Tabs activeTab={this.props.activeTab}
onChange={(tabId) => this.setProps({ activeTab: tabId })} ripple>
<Tab>Stack</Tab>
<Tab>GitHub</Tab>
<Tab>Twitter</Tab>
</Tabs>
<section>
<div className="content">Content for the tab: {this.props.activeTab}</div>
</section>
</div>
);
}
});

容器

import React from 'react';
import TimeLine from './timeline';
import { connect } from 'react-redux';
import { getStackoverflow } from 'api/timeline';

const TimeLineContainer = React.createClass({

componentWillMount: function() {
getStackoverflow();
},

render: function() {
return (
<TimeLine {...this.props} />
)
}
});

const stateToProps = function(state) {
return {
timeline: state.timelineReducer.timeline
}
}

const dispatchToProps = function(dispatch) {
return {
onClick: () => {console.log('timeline was clicked')}
}
}

export default connect(stateToProps, dispatchToProps)(TimeLineContainer)

reducer

var timelineInitialState = {
github: [],
gist: [],
stackoverflow: [],
twitter: [],
activeTab: 2
}

export default function(state = timelineInitialState, action) {
switch (action.type) {
case 'GET_GITHUB':
//TODO: implement.
break;
case 'GET_GIST':
//TODO: implement.
break;
case 'GET_STACKOVERFLOW':
var stackoverflowState = Object.assign({}, state)
stackoverflowState.stackoverflow = action.stackoverflow;
return stackoverflowState;
break;
case 'GET_TWITTER':
//TODO: implement.
break;
default:
return state;
}
}

最佳答案

看起来您在没有牢牢掌握 React 的情况下就开始使用 Redux。我不建议这样做,因为您现在似乎有些困惑。

Thinking in React是一个很好的指南,我建议您在使用 Redux 之前先通读它并熟悉 React 中的状态所有权的概念。

在 React 中,随时间变化的事物(“状态”)始终由某个组件“拥有”。有时它是使用此状态进行渲染的同一组件。有时需要同步许多组件,以便将状态“提升”到某个可以管理它们的父组件,并通过 props 传递该信息。每当状态发生变化时,它们都会得到更新。

这里的重要部分是 props应该由 parent 接收。如果一个组件想要改变它自己的 props,这是一个问题的征兆:

  1. 要么你应该使用state对于此组件,您可以调用 setState
  2. 或者你的组件需要访问像onChange这样的回调属性所以它可以“询问”要更改的值

在第一种情况下,你的代码看起来像这样,而且它是有效的 React:

export default React.createClass({
getInitialState: function() {
return { activeTab: 0 }
},

render: function() {
return (
<div className="demo-tabs">
<Tabs activeTab={this.state.activeTab}
onChange={(tabId) => this.setState({ activeTab: tabId })} ripple>
<Tab>Stack</Tab>
<Tab>GitHub</Tab>
<Tab>Twitter</Tab>
</Tabs>
<section>
<div className="content">Content for the tab: {this.state.activeTab}</div>
</section>
</div>
);
}
});

但是,您可以使用 <Tabs> 继续您已经使用的模式内部组件,并将状态提升到更高。然后你的组件需要接受 onChange它将传递给 <Tabs> 的 Prop .现在它不知道状态是如何更新的,并且不保存状态:

export default React.createClass({
render: function() {
return (
<div className="demo-tabs">
<Tabs activeTab={this.props.activeTab}
onChange={this.props.onChange} ripple>
<Tab>Stack</Tab>
<Tab>GitHub</Tab>
<Tab>Twitter</Tab>
</Tabs>
<section>
<div className="content">Content for the tab: {this.props.activeTab}</div>
</section>
</div>
);
}
});

这两种方法都没有好坏之分,它们用于不同的目的。当状态与应用程序的其余部分无关时,第一个更方便,当其他远程组件恰好也需要它时,第二个更方便。确保您了解这两种方法的权衡。

即使采用第二种方法,某些东西也必须保持状态。它可以是另一个组件,或者(这就是 Redux 的用武之地)它可以是一个单独的数据存储,如 Redux 存储。在这种情况下,而不是供应 onChange从父组件中,您将使用 connect()绑定(bind) onChange支持它注入(inject)调度 Redux 操作:

const mapStateToProps = (state) => {
return {
activeTabId: state.activeTabId
}
}

const mapDispatchToProps = (dispatch) => {
return {
onChange: (tabId) => dispatch({ type: 'SET_ACTIVE_TAB', tabId })
}
}

在你的 reducer 中,你可以处理这个 Action :

const activeTabId = (state = 0, action) => {
switch (action.type) {
case 'SET_ACTIVE_TAB':
return action.tabId
default:
return state
}
}

const reducer = combineReducers({
activeTabId,
// other reducers
})

const store = createStore(reducer)

在这两种情况下我们都不需要 setProps .您可以:

  • 让组件拥有状态并使用setState ,
  • 让它接受 activeTabIdonChange Prop 并从树中更高的组件管理它们,该组件将使用 setState , 或
  • 你可以将状态处理完全从组件中移出到类似 Redux 的东西中,但你的组件仍然会接受 activeTabIdonChange作为 Prop 。

关于javascript - 如何避免在 React 中使用 setProps?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36634522/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com