React HOC не может передать реквизит расширенному компоненту - PullRequest
3 голосов
/ 21 марта 2019

У меня есть этот кусок кода:

const defaultValue = new Api()

const ApiContext = React.createContext(defaultValue);
const ApiProvider = ApiContext.Provider;
const ApiConsumer = ApiContext.Consumer;


const withApi = (Enhanced: any) => {

    return (        
        <ApiConsumer>
            {api => {
                return <Enhanced api={api}/>;
            }}
        </ApiConsumer>
    )
}

export default ApiContext;
export {ApiContext, ApiProvider, ApiConsumer, withApi};

И в моем приложении у меня есть что-то вроде этого:

const api = new ApiManager({...});

ReactDOM.hydrate(
    <Provider store={store}>
        <BrowserRouter>
            <ApiProvider value={api}>
                <Main />
            </ApiProvider>
        </BrowserRouter>
    </Provider>, document.querySelector('#app')
);

Но эта строка return <Enhanced api={api}/>; вызывает следующие ошибки:

1.

Предупреждение: React.createElement: тип недействителен - ожидается строка (для встроенных компонентов) или класс / функция (для составного компоненты) но получил: Ты случайно экспортировать литерал JSX вместо компонента?

2.

Неопределенное нарушение инварианта: недопустимый тип элемента: ожидается строка (для встроенных компонентов) или класс / функция (для составного компоненты), но получил: объект.

3.

Uncaught (in promise) Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of `Context.Consumer`.

Что я тут не так делаю? Как я могу передать api prop в расширенный компонент?

[EDIT]

Вот как я называю свой компонент:

App.tsx

class App extends React.Component {
    render() {
        return (
            <React.Fragment>                
                    <Switch>
                        {routes.map(({ path, exact, component: C }) => {

                            return <Route
                                key={path}
                                path={path}
                                exact={exact}
                                render={(props) => {

                                    return withApi(<C {...props} />);

                                }} />
                        })}
                    </Switch>                
            </React.Fragment>
        )
    }
}

1 Ответ

1 голос
/ 21 марта 2019

Вы неправильно написали свой withApi HOC. Он должен возвращать функциональный компонент вместо JSX

const withApi = (Enhanced: any) => {
  return (props) => {
    return (        
        <ApiConsumer>
            {api => {
                return <Enhanced {...props} api={api}/>;
            }}
        </ApiConsumer>
    )
  }
}

и используйте его как

class App extends React.Component {
    render() {
        return (
            <React.Fragment>                
                    <Switch>
                        {routes.map(({ path, exact, component: C }) => {
                            const Comp = withApi(C);
                            return <Route
                                key={path}
                                path={path}
                                exact={exact}
                                render={(props) => {

                                    return <Comp {...props}/>

                                }} />
                        })}
                    </Switch>                
            </React.Fragment>
        )
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...