2016-05-13 5 views
1

У меня есть определенный сценарий в моем универсальном проекте response/redux/express (на стороне сервера).Redux/React - Почему я не могу связать состояние с this.props на компоненте, который находится в iframe?

(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 маршрута: локальный: 3000/предварительный, реагировать-маршрутизатор будет использовать AnotherView компонент.

(2) В настоящее время сосредоточены на ThemeIndex компонента: [ThemeIndex.jsx]

export default class ThemeIndex extends Component { 
    render() { 
    return (
     <div> 
     <h2>Index</h2> 
     <Frame /> 
     <Control /> 
     </div> 
    ); 
    } 
} 

(3) компонент кадров следующим образом: [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 is 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.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:

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) Теперь я ключа некоторые слова на входе в компонент управления. Когда вход onChange вызовет addTodo Функция действия для отправки действия в редукторе, наконец, измените состояние. В общем случае изменение состояния будет влиять на компонент Frame и компонент AnotherView, потому что я использовал react-reduxconnect, привяжите свойство состояния к компоненту this.props.

Но на самом деле есть проблема в AnotherView Компонент. в Кадр компонент, console.log Значение отображает введенный вами текст правильно.В компоненте AnotherView, даже подключения обратного вызова будет триггер (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> 
); 

, то я могу связать state свойства на this.props в AnotherView компонент успешно, а затем вставьте {text} на JSX HTML, вы можете увидеть изменения значения в реальном времени, когда вы вводите значение ввода на Управление Компонент. если я использую iframe для ссылки AnotherView Компонент будет его страницей, вы не видите никакого значения изменения {text}, потому что мое текстовое значение по умолчанию - пустое строковое значение.

Как связать state свойствам this.props в компоненте, который находится в iframe, когда состояние меняется?

Update Я не могу получить последнюю state в IFRAME (источник Реагировать компонент), когда я меняя state в другом компоненте, а на самом деле mapStateToProps сработал! (Означает источник IFrame компонент), но его состояние не последняя в mapStateToProps функция. это действительно не касается библиотеки react-redux?

Это последнее состояние должно быть в компоненте: enter image description here

Ниже IFrame источник компонент, он не может получить последнее состояние: enter image description here

ответ

1

Если загрузить приложение в IFRAME от тег сценария, он загрузит отдельный экземпляр приложения. Это точка iframes: они изолируют код.

Два отдельных экземпляра приложения не будут «видеть» обновления друг от друга. Это похоже на открытие приложения в двух отдельных вкладках браузера. Если вы не добавите какой-либо метод связи между ними, они не будут делить состояние.

Непонятно, почему вы хотите визуализировать рамку, а не компонент напрямую. Но если вам действительно нужны фреймы, простой вариант заключается в том, чтобы использовать компонент в, а не загружать отдельное приложение. Вы можете использовать такую ​​библиотеку, как https://github.com/ryanseddon/react-frame-component. Или, проще говоря, вы просто не можете использовать фреймы вообще, так как неясно, какую цель они служат. Обычно люди хотят, чтобы они изолировали экземпляр приложения, но это противоречит тому, что вам кажется нужным.

+0

Спасибо вашему ответу, вдохновите меня найти другой способ достичь моего объекта. Я должен отображать в iframe, потому что я хотел бы использовать JSX для создания шаблона для рендеринга шаблона в iframe, я не хочу использовать другой механизм шаблонов, например, jade, handleBar ... и т. Д. Если я хотел бы синхронизировать данные о состоянии iframe, возможно ли передать последнее состояние в iframe для связи? –

+0

Я не понимаю, что JSX имеет отношение к iframes. :-( –

+0

Если вы используете что-то вроде 'response-frame-component', вам нужно будет удалить'

 Смежные вопросы

  • Нет связанных вопросов^_^