【发布时间】:2016-09-10 03:32:40
【问题描述】:
我的 react/redux/express 通用项目(服务器端渲染)中有一个特定场景。
(1)首先我这样定义我的路由:[ routes.jsx ]
export default (
<Route component={App} path="/">
<Route component={MainView} path="main">
<IndexRoute component={ThemeIndex}></IndexRoute>
</Route>
<Route component={AnotherView} path="preview" />
</Route>
);
如你所见,当 url route 为:localhost:3000/preview 时,react-router 将使用 AnotherView 组件。
(2)现在关注 ThemeIndex 组件:[ ThemeIndex.jsx ]
export default class ThemeIndex extends Component {
render() {
return (
<div>
<h2>Index</h2>
<Frame />
<Control />
</div>
);
}
}
(3)Frame组件如下:[Frame.jsx]
class Frame extends Component {
render() {
const { text, uid } = this.props.infos;
const themeUrl = `http://localhost:3000/preview?id=${uid}`;
//console.log('Frame theme:', text);
//console.log('Frame uid:', uid);
return (
<div className="col-md-8 panel panel-default">
<div className="embed-responsive embed-responsive-16by9 panel-body">
<iframe src={themeUrl}></iframe>
</div>
<div className="details" >
{text}
</div>
</div>
);
}
}
export default connect(
(state) => {
return {
infos: state.infos
}
}
)(Frame);
这里我使用了iframe标签,它的src是http://localhost:3000/preview?id=xxxx,也就是说它将AnotherView组件链接到iframe的页面。
(4)AnotherView 组件如下:
class AnotherView extends Component {
render() {
const { text, uid } = this.props.infos;
//console.log('AnotherView theme:', text);
//console.log('AnotherView uid:', uid);
return (
<div>
<div >Another View</div>
<div>
{text}
</div>
<div>{uid}</div>
</div>
);
}
}
export default connect(
(state) => {
console.log('another view trigger state:', state);
return {
infos: state.infos
}
}
)(AnotherView);
(4)我有控制组件来制作动态值:[ Component.jsx ]
class Control extends Component {
render(){
var uid = () => Math.random().toString(34).slice(2);
return (
<input
onChange={(event) => this.props.addTodo({text:event.target.value, uid:uid()})
/>
)
}
}
export default connect(
(state) => {
return {
infos: state.infos
}
}
)(Control);
(5)列出额外的文件,Action和Reducer: [动作.js]
export function addTodo (attrs) {
return {
type: 'ADD_TODO',
attrs
};
}
[reducer.js]
export default (state = {text:'', uid:''}, action) => {
switch(action.type) {
case 'ADD_TODO':
return Object.assign({}, state, action.attrs);
default:
return state;
}
}
这是 server.js 上的 Store 配置:
app.use( (req, res) => {
console.log('server - reducers:', reducers);
const location = createLocation(req.url);
const reducer = combineReducers({infos: infosReducer});
const store = applyMiddleware(promiseMiddleware)(createStore)(reducer);
match({ routes, location }, (err, redirectLocation, renderProps) => {
.......
function renderView() {
const createElement = (Component, props) => (
<Component
{...props}
radiumConfig={{ userAgent: req.headers['user-agent'] }}
/>
);
const InitialView = (
<Provider store={store}>
<RoutingContext
{...renderProps}
createElement={createElement} />
</Provider>
);
const componentHTML = renderToString(InitialView);
const initialState = store.getState();
......
我的应用程序状态是这样的:
{
infos:{
text: '',
uid: ''
}
}
(6)现在我在 Control 组件中输入一些单词。当输入 onChange 会触发 addTodo action 函数在 reducer 中 dispatch action,最终改变 state。一般来说,状态变化会影响Frame组件和AnotherView组件,因为我使用了react-reduxconnect,将state属性绑定到组件上的this.props。
但其实AnotherView组件有问题。在 Frame 组件中,console.log 值正确显示您输入的文本。在AnotherView组件中,连connect回调都会被触发(console.log会打印'another view trigger state: ...'),渲染中的console.log是undefined,比如:
console.log('AnotherView theme:', text); //return AnotherView theme: undefined
console.log('AnotherView uid:', uid); //return AnotherView uid: undefined
我找到了主要原因:AnotherView 组件在iframe。因为如果我去掉iframe,直接把AnotherView组件放在这里,像这样:
return (
<div className="col-md-8 panel panel-default">
<div className="embed-responsive embed-responsive-16by9 panel-body">
<AnotherView/>
</div>
<div className="details" >
{text}
</div>
</div>
);
然后我可以在AnotherView组件中绑定this.props上的state属性成功,然后在JSX html上插入{text},你可以看到当你输入值时值实时变化控制组件。如果我使用 iframe 将 AnotherView 组件链接为它的页面,您看不到任何更改的 {text} 值,因为我的文本默认值为空字符串值。
当状态改变时,如何将state 属性绑定到iframe 中的组件中的this.props?
更新
我无法在 iframe 中获得最新的state(源是 React 组件),当我在另一个组件中更改 state 时,实际上触发了 mapStateToProps!(表示 iframe 源组件)但它的状态不是最新的mapStateToProps 功能。它与react-redux 库无关吗?
【问题讨论】: