Pascal ошибка регистра для динамического добавления имени компонента в метод рендеринга Reactjs маршрута - PullRequest
0 голосов
/ 02 августа 2020

Я пытаюсь настроить динамический рендеринг компонента. Имя компонента извлекается из состояния. Имя указано в регистре pascal, но по-прежнему вызывает ошибку pascal. Например, значение, которое я пробую, - «HeroBanner». Если я поставлю прямо, все работает нормально. Если получить это динамически через состояние и затем присвоить его переменной, это приведет к обратным результатам с ошибкой pascal case.

Вот мой код

import '@babel/polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Redirect, withRouter} from 'react-router-dom'
import { createBrowserHistory } from 'history';
import HeroBanner from './IssueList.jsx';
import IssueTable from './IssueTable.jsx';
import {PropTypes} from 'prop-types';
import {Header} from './Header.jsx';
import Demo from './Cropcrop.jsx';
import {Receiver} from 'react-file-uploader';

const contentNode = document.querySelector("#contents");
const NoMatch = () => <p>404 no result</p>

class App extends  React.Component{
    
    constructor(){
        super();
        this.state = {
            currentLocation: ""
        }
        
        this.changeLocation = this.changeLocation.bind(this)
    }
    
    changeLocation(e){
        
        this.setState({
            currentLocation: e
        })
        
    }
    
    render(){
        
        const Component= this.state.currentLocation === ''? "HeroBanner" : this.state.currentLocation
        
        return(
                <div>
                    <BrowserRouter>
                        <Header/>
                          <Redirect from="/" to="/selection"></Redirect>
                            <Switch>
                                <Route exact path={"/"+ Component} render={(props) => <Component />} />
                                <Route exact path="/selection" render={(props) => <IssueTable {...props} onChange={this.changeLocation} />}  />
                                <Route  path="/*" component={NoMatch}/>
                                </Switch>
                     </BrowserRouter>
                <Component/>
                </div>
        )
        }

        }





const RoutedApp = () => (
    <App/>
);


ReactDOM.render(<RoutedApp />, contentNode);

if(module.hot){
    module.hot.accept();
}

Ответы [ 2 ]

2 голосов
/ 02 августа 2020

Вам не разрешено динамически указывать компонент в React (указав строку вместо типа):

render={(props) => <Component />}

Это должно быть что-то вроде:

const Component = this.state.currentLocation === '' ? HeroBanner : SomeOtherComponent;

У меня была аналогичная ситуация в проекте, над которым я работаю, и в итоге я создал карту между определенным строковым значением (в моем случае это было имя вкладки, из URL-адреса) и тип компонента:

const componentsMap = {
   home: HomeComponent,
   about: AboutComponent,
   ...
}

const Component = componentsMap[myStringValue];

Этот последний фрагмент кода разрешен, поскольку вы ссылаетесь на тип компонента , а не на какую-то обычную строку, которая не может быть используется как действительный JSX.

Что касается маршрутизации , я заметил, что вы просто установили какое-то строковое значение в состоянии и ожидаете, что маршрутизация произойдет. Это не так, поскольку react-router-dom отслеживает изменения в URL-адресе / пути браузера, и вам, вероятно, следует выполнить ручную маршрутизацию в вашем случае, чтобы перейти к другому виду <Route>. В приведенном ниже примере я выполняю навигацию в обработчике onDropdownChange при изменении раскрывающегося списка.

Мне нравится минимизировать повторение строк, представляющих имена маршрутов и имена компонентов, чтобы иметь значение dynamic c в качестве параметра в URL-адрес. Затем компонент <Subroute> обрабатывает все сопоставления для этой группы маршрутов (вам может не понадобиться этот дополнительный уровень вложенности, зависит от размера приложения). В созданной мной песочнице вы можете увидеть карту, о которой я говорил в комментариях. Вы выбираете соответствующий компонент на основе параметра tab в URL-адресе (который содержит значение, выбранное из раскрывающегося списка).

Пример здесь

ИЗМЕНИТЬ для вопроса в комментариях (11 августа 2020 г.):

Вы также можете использовать изящный трюк, чтобы настроить то, что будет отображаться на маршруте, например (без необходимости используйте рендеринг маршрута):

<Route exact path={path}>
   <ComponentOne {...someProps} />
   <ComponentTwo {...someOtherProps} />
   <p>Some html too</p>
</Route>

Чтобы использовать вместо него render (возможно, менее читаемый, я предпочитаю первый вариант, просто передайте необходимый JSX, обернув его Fragment, если необходимо):

<Route
    exact
    render={routeProps => (
        <Fragment>
            <ComponentOne {...someProps} />
            <ComponentTwo {...someOtherProps} />
            <p>Some html too</p>
        </Fragment>
    )}
/>
0 голосов
/ 02 августа 2020

Хотя приведенный выше ответ абсолютно правильный. Вот как я следил за логами выше c.

import '@babel/polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Redirect, withRouter} from 'react-router-dom'
import { createBrowserHistory } from 'history';
import HeroBanner from './IssueList.jsx';
import IssueTable from './IssueTable.jsx';
import {PropTypes} from 'prop-types';
import {Header} from './Header.jsx';
import Demo from './Cropcrop.jsx';
import {Receiver} from 'react-file-uploader';
const contentNode = document.querySelector("#contents");
const NoMatch = () => <p>404 no result</p>

const componentList={
    HeroBanner: HeroBanner
}

class RoutedApp extends  React.Component{
    
    constructor(){
        super();
        this.state = {
            currentLocation: ""
        }
        
        this.changeLocation = this.changeLocation.bind(this)
    }
    
    changeLocation(e){
        console.log(e)
        this.setState({
            currentLocation: e
        })
        
    }
    
    render(){
        
        const Component= this.state.currentLocation === '' ? NoMatch : componentList[this.state.currentLocation]
        console.log(Component)
        return(
                <div>
                    <BrowserRouter>
                        <Header/>
                          <Redirect from="/" to="/selection"></Redirect>
                            <Switch>
                                <Route exact path={"/"+ this.state.currentLocation} component={Component} />
                                <Route exact path="/selection" render={(props) => <IssueTable {...props} onChange={this.changeLocation} />}  />
                                <Route  path="/*" component={NoMatch}/>
                                </Switch>
                     </BrowserRouter>
             </div>
        )
     }
 }




ReactDOM.render(<RoutedApp />, contentNode);

if(module.hot){
    module.hot.accept();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...