Javascript 使用<;通过上下文传递存储;供应商>;在基于connect()的方案中不工作
编辑:总结-我的问题的最初原因实际上是一个打字错误:由于大写字母“G”,它不起作用 然而,善意的回答者不仅解决了打字错误,而且还解决了我所采取的方法中的错误前提——如果您也正在使用提供商和connect通过商店,他们的回答与您相关。我已更新问题的标题以反映这一点Javascript 使用<;通过上下文传递存储;供应商>;在基于connect()的方案中不工作,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,编辑:总结-我的问题的最初原因实际上是一个打字错误:由于大写字母“G”,它不起作用 然而,善意的回答者不仅解决了打字错误,而且还解决了我所采取的方法中的错误前提——如果您也正在使用提供商和connect通过商店,他们的回答与您相关。我已更新问题的标题以反映这一点 我试图按照中的说明进行操作,但由于使用react redux中的传递了商店,我感到很难过 我有一个根组件: export default class Root extends Component { render() {
我试图按照中的说明进行操作,但由于使用react redux中的
传递了商店,我感到很难过
我有一个根组件:
export default class Root extends Component {
render() {
const { store } = this.props
return (
<Provider store={store}>
<div>
<ReduxRouter />
<DevTools />
</div>
</Provider>
)
}
}
(不是我的代码,这是一个支持react native和browser client的框架,我正在使用它开始工作)
我错过了什么
我正在从视频中复制此内容-请注意,AddTodo组件没有使用connect()进行“包装”:
const AddTodo=(props,{store})=>{
让输入;
返回(
{
输入=节点;
}} />
{
仓库调度({
键入:“ADD_TODO”,
id:nextTodoId++,
文本:input.value
})
input.value='';
}}>
添加待办事项
);
};
AddTodo.contextTypes={
存储:React.PropTypes.object
};
更新:
store.GetState()
不是一个方法
store.getState()
是一种方法
您对
connect
的使用有点倒退
connect
将函数作为第一个参数,让您可以访问商店和道具。传递给另一侧的是视图组件将作为其道具接收的对象
const MyWidget = (props) => {
const { title, data } = props;
return (<div>{title}{data}</div>);
};
const MyWidgetContainer = connect((store, props) => {
return { title: props.title, data: store.a.b.widget.data };
})(MyWidget);
MyWidget现在可以单独访问商店
在您的情况下,您没有将所看到的transformer功能赋予connect
,而是将其应用于
,这意味着如果您在应用程序中使用HomeContainer
,则Home
将有权访问商店
这是100%的好,但除非您也包装您的演示组件,否则您的演示组件将没有存储访问权限。这也没关系,但这意味着Home
现在需要传递组件所需的道具
// Home
Home {
render () {
{ a, b, c } = this.props;
return (
<MyWidget a={ a } b={ b } c={ c } />
);
}
}
container = connect(/* ... */)(Home);
//主页
家{
渲染(){
{a,b,c}=this.props;
返回(
);
}
}
容器=连接(/*…*/)(主);
是正确的,但我想澄清几件事
您似乎对表示组件和容器组件以及connect()
的角色有很多困惑。我建议你再看一次相关的视频,并确保看到最后
实际上,store.GetState()
不是有效的方法store.getState()
is
如果手动使用store.getState()
,则必须在某个地方使用store.subscribe()
,以便始终获得最新状态。您从视频中粘贴的示例AddTodo
组件本身无法工作-它只在视频中工作,因为我们在顶部有一个存储。订阅(渲染)
本课程后面的视频将讨论如何从顶部重新渲染会变得麻烦,此时我们将介绍容器组件。随后我们展示了使用connect()
生成容器组件比手工编写更容易。在这种情况下,connect()
负责订阅存储
在您的案例中,仅在connect()
中包装Home
,没有任何效果connect()
生成订阅存储的容器组件,但如果不指定mapstatetops
参数,它甚至不会订阅存储使用connect()
是手动使用store.getState()
、store.subscribe()
和contextTypes
的有效替代方法。在某些东西上使用connect()
和调用store.getState()
或指定contextTypes
,都是没有意义的
因此,再次总结一下:
store.getState()和store.subscribe()是低级API。如果你决定使用它们,你必须一起使用它们;一个没有另一个是没有意义的
connect()
负责调用getState()
和subscribe()
并通过道具将必要的信息传递给子组件。如果使用connect()
,则永远不需要store.getState()
、store.subscribe()
、或contextTypes
。connect()
的全部目的就是将它们抽象出来
这些课程教给你所有这些工具,告诉你没有魔法。但是,通常不应该在实际应用程序中使用store.getState()
和store.subscribe()
。除非您访问低级API有非常具体的原因,否则您几乎应该只使用connect()
我将大致如下重写您的代码:
// ProjectSummary is a presentational component
// that takes projects as a prop and doesn't care
// where it comes from.
const ProjectsSummary = ({ projects }) => {
return (
<div className="home-projects col-md-10">
<h3>Projects</h3>
<ul>
{projects.map(p => <li key={p.id}>{p.contract.client}</li>)}
</ul>
</div>
)
}
// Home by itself is also a presentational component
// that takes projects as a prop. However we will
// wrap it in a container component below using connect().
// Note that I got rid of inheritance: it's an anti-pattern
// in React. Never inherit components; instead, use regular
// composition and pass data as props when necessary.
const Home = ({ projects }) => (
<div className="home-page container-fluid">
<BasePage />
<HomeLeftBar />
<HomePageHeader />
<ProjectsSummary projects={projects} />
</div>
)
// How to calculate props for <Home />
// based on the current state of the store?
const mapStateToProps = (state) => ({
projects: state.projects
})
// Generate a container component
// that renders <Home /> with props from store.
export default connect(
mapStateToProps
)(Home)
//ProjectSummary是一个表示组件
//这将项目视为道具,并不在意
//它来自哪里。
常量项目汇总=({projects})=>{
返回(
项目
{projects.map(p=>- {p.contract.client}
)}
)
}
//家本身也是一种表现成分
//这将项目视为支柱。无论如何,我们会
//使用connect()将其包装在下面的容器组件中。
//注意,我去掉了继承:这是一种反模式
//在反应中。永远不要继承组件;相反,使用常规的
//必要时合成并传递数据作为道具。
const Home=({projects})=>(
)
//如何计算道具
//基于商店的当前状态?
常量MapStateTops
const AddTodo = (props, { store }) => {
let input;
return (
<div>
<input ref={node => {
input = node;
}} />
<button onClick={() => {
store.dispatch({
type: 'ADD_TODO',
id: nextTodoId++,
text: input.value
})
input.value = '';
}}>
Add Todo
</button>
</div>
);
};
AddTodo.contextTypes = {
store: React.PropTypes.object
};
const MyWidget = (props) => {
const { title, data } = props;
return (<div>{title}{data}</div>);
};
const MyWidgetContainer = connect((store, props) => {
return { title: props.title, data: store.a.b.widget.data };
})(MyWidget);
import MyWidget from "./components/my-widget/";
//...
render ( ) {
return (
<MyWidget title="My Title" />
);
}
// Home
Home {
render () {
{ a, b, c } = this.props;
return (
<MyWidget a={ a } b={ b } c={ c } />
);
}
}
container = connect(/* ... */)(Home);
// ProjectSummary is a presentational component
// that takes projects as a prop and doesn't care
// where it comes from.
const ProjectsSummary = ({ projects }) => {
return (
<div className="home-projects col-md-10">
<h3>Projects</h3>
<ul>
{projects.map(p => <li key={p.id}>{p.contract.client}</li>)}
</ul>
</div>
)
}
// Home by itself is also a presentational component
// that takes projects as a prop. However we will
// wrap it in a container component below using connect().
// Note that I got rid of inheritance: it's an anti-pattern
// in React. Never inherit components; instead, use regular
// composition and pass data as props when necessary.
const Home = ({ projects }) => (
<div className="home-page container-fluid">
<BasePage />
<HomeLeftBar />
<HomePageHeader />
<ProjectsSummary projects={projects} />
</div>
)
// How to calculate props for <Home />
// based on the current state of the store?
const mapStateToProps = (state) => ({
projects: state.projects
})
// Generate a container component
// that renders <Home /> with props from store.
export default connect(
mapStateToProps
)(Home)