React - Ссылка перенаправляет на элемент, но не обновляет компонент

Когда я нажимаю на StageItem «Подробности», URL-адрес изменяется, но компонент Stage не обновляет данные. Я безуспешно пытался использовать Switch и withRouter, потому что совершенно не знаю, как их использовать в моем случае. Заранее благодарим за ответы. Мой код:

Приложение

class App extends Component {
  render() {
    return (
        <BrowserRouter>
          <div className = "App">
            <Header/>
            <div className = "container">
                <div className = "row">
                    <Route path='/' component = {InputContainer}/>
                    <Route path='/' component = {() => <StagesList todos = {this.props.todos}/>} />
                    <Route path='/:stage_id' render = {(props) => <Stage {...props} todos = {this.props.todos}/>} />
                </div>
            </div>
          </div>
        </BrowserRouter>
    );
  }
}

const mapStateToProps = state => {
    return {
        todos: state.todos
    };
};

const mapDispatchToProps = {};

export const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App);

StageItem

export const StageItem = ({ todo, id, handleRemoveTodo}) => {

    return(
        <li className = "stage_item" key = {id}><span onClick = {() => handleRemoveTodo(id)}><FontAwesomeIcon className = "fa" icon = "trash" />&nbsp;{todo.tour} - {todo.duration.hours}:{String(todo.duration.minutes).padStart(2,"0")}:{String(todo.duration.seconds).padStart(2,"0")} - {todo.distance} km - {todo.avgSpeed} km/h - {todo.maxSpeed} km/h</span><Link to = {'/'+todo.id}>Details</Link></li>
    )

};

StagesList

export class StagesListC extends React.Component{

    render(){

        return(
            <div className = "col-12 col-sm-12 col-md-12 col-lg-12">
                <SectionTitle title = "Stage list"/>
                {this.props.todos.length>0 ?
                <ul className = "todo-list">
                    {this.props.todos.map((todo) => <StageItem
                        key = {todo.id}
                        id = {todo.id}
                        todo = {todo}
                        handleRemoveTodo = {this.props.handleRemoveTodo}
                    />)}
                </ul>
                :
                <div>You have no stages</div>}
            </div>
        )
    }

}

const mapStateToProps = dispatch => bindActionCreators({
    handleRemoveTodo
}, dispatch)

const mapDispatchToProps = { handleRemoveTodo };

export const StagesList = connect(mapStateToProps, mapDispatchToProps)(StagesListC);

Полный проект: Ссылка на сайт

Кто-нибудь поможет ???

scartout 30.11.2018 22:28
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
1
1 858
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо добавить exact к вашим маршрутам /, если вы не хотите видеть InputContainer и StagesList, пока вы находитесь на маршруте :stage_id.

<div className = "row">
    <Route path='/' exact component = {InputContainer}/>
    <Route path='/' exact component = {() => <StagesList todos = {this.props.todos}/>} />
    <Route path='/:stage_id' render = {(props) => <Stage {...props} todos = {this.props.todos}/>} />
</div>

Также есть ошибка в вашем компоненте Stage.

todo.id - целое число, а stage_id - строка. Чтобы исправить это, вы можете преобразовать оба в строку, например.

let stage = todos.filter((todo) => String(todo.id) === String(id));

UPD:

Если вы хотите видеть компоненты StageList и Stage все время, вам необходимо исправить компонент Stage. Компонент Stage обновляет свое значение state.stage только один раз при запуске componentDidMount. Все последующие обновления не обновляют значение stage.stage. Вы можете реализовать метод жизненного цикла componentWillReceiveProps и обновлять значение stage.stage при изменении свойств. В качестве альтернативы вы не используете state.stage и вычисляете значение stage на лету в методе render, например:

class Stage extends React.Component {

    getStage = () => {
        const todos = this.props.todos || [];
        let id = this.props.match.params.stage_id;
        return todos.filter((todo) => String(todo.id) === String(id))[0];
    }

    render() {

        const stage = this.getStage();

        if (!stage) return null;

        return <div className = "col-12 col-sm-12 col-md-12 col-lg-12">
            <SectionTitle title = "Single stage"/>
            <div>Id: {stage.id}</div>
            <div>Distance: {stage.distance}</div>
            <div>Duration: {stage.duration.hours}:{String(stage.duration.minutes).padStart(2, "0")}:{String(stage.duration.seconds).padStart(2, "0")}</div>
            <div>Average speed: {stage.avgSpeed} km/h</div>
            <div>Max speed: {stage.maxSpeed} km/h</div>
        </div>
    }
}

Спасибо за ответ. Я обнаружил эту ошибку '===' ранее. С «точным» работает как положено. Но самый важный вопрос для меня был - можно ли сохранить «StagesList» и показать «Stage» и переключить «Stage», щелкнув «StagesList»?

scartout 01.12.2018 16:36

@scartout Да, это возможно. Проблема в том, что вы обновляете компонент Stage только один раз при запуске componentDidMount. Самым простым решением было бы перенести логику фильтрации в метод render. См. Обновленный ответ.

euvs 02.12.2018 03:25

Прекрасно работает! Благодарю за ваш ответ.

scartout 02.12.2018 16:08

Другие вопросы по теме