Контекст в компоненте "без гражданства"?

У меня есть следующий код в компоненте, и я хотел бы, чтобы компонент без состояния имел доступ к этой части кода:

Главный компонент:

function createApp(store, communityIds) {
const App = React.createClass({

    childContextTypes: {
        localizedString: React.PropTypes.func,
    },

    getChildContext: function() {
        return {
            localizedString: function(key, fallback) {
                return getKey(key, fallback);
            },
        };
    },

    render: function() {
        return (
            <Provider store={store}>
                <Client communityIds={communityIds}/>
            </Provider>
        );
    },
});

return <App/>;
}

Stateless:

export default () => (dispatch, getState) => {
    const state = getState();

    const token = state.user.get('token');

    if (!token) {
        throw new Error('test'); // this.context.localizedString does not work
    }
}

Ответ 1

То, что вы предоставили в своем определении "функции без сохранения состояния", не является функцией без сохранения состояния. Вы предоставили своего создателя действия в качестве Thunk. Я предполагаю, что вы хотели вставить код для своего клиентского компонента. Чтобы получить доступ к контексту в компоненте без состояния, ваш клиентский компонент будет делать что-то вроде этого (что описано здесь)

const Client = (props, context) => {   
    return  <div >{context.localizedString("someKey", "someFallback")} </div>
}

Client.contextTypes = {
    localizedString: React.PropTypes.func
}

export default Client

Ответ 2

Используйте второй параметр компонента без состояния

const MyStatelessComponent = (props, context) => { 
   const onGoButtonClick = () => {
      context.router.push('https://www.google.co.in');
   };

   return(
      <div>
         <button onClick={() => onButtonClick()}>
            {props.buttonName}
         </button>
      </div>
   );
}

MyStatelessComponent.propTypes = {
   buttonName: PropTypes.string.isRequired,
};

MyStatelessComponent.contextTypes = {
   router: React.PropTypes.object.isRequired,
};

export default MyStatelessComponent;

Ответ 3

Другим решением является функция самозапуска:

export default (Component=>(
  Component.contextTypes = {
    localizedString: React.PropTypes.func
  }) && Component
)((props, context)=>{
  return  <div>{context.localizedString("someKey", "someFallback")}</div>
})

Или, если вы определяете контекстные типы отдельно для повторного использования, вы можете сделать:

//addContextTypes.js
export default function(Component){
  return (Component.contextTypes = {
    localizedString: React.PropTypes.func
  }) && Component
}

//component.jsx
import addContextTypes from './addContextTypes'
export default addContextTypes((props, context)=>{
  return  <div>{context.localizedString("someKey", "someFallback")}</div>
})

Ответ 4

У меня такой же вопрос. Современный способ (в 2019 году) - использовать хук useContext (contextName). Документы: https://reactjs.org/docs/hooks-reference.html#usecontext

  const dumbComp = (props) => { 
       const context = useContext(contextName);
          return(
             <div>
             ...
          </div>
       );
    }

Ответ 5

У меня был тот же вопрос, но я был на Expo SDK 32, то есть у меня нет доступа к хукам.

Вот как я этого добился:

import { reduxForm } from 'redux-form'
import { ReduxFormContext } from 'redux-form/lib/ReduxFormContext'

const ShowFormName = () => (
  <ReduxFormContext.Consumer>
    {
      ({ form }) => <Text>{form}</Text>
    }
  </ReduxFormContext.Consumer>
)

export default reduxForm({ form: 'formName' })(ShowFormName)