У меня две составляющие. Эти компоненты расположены на разных маршрутах. Компонент CreateItem дает мне возможность создавать новые элементы. Сохраняю новые элементы в массиве. Массив будет включать новые созданные элементы. Я хочу отправить этот измененный массив компоненту 'Main' , где я буду повторять эти элементы и отображать их в виде списка.

Вот мой код:

1) файл index.js:

import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom'
import {Main} from "./components/Main"
import {CreateItem} from "./components/CreateItem"
import {CurrentItem} from "./components/CurrentItem"


render(
    <BrowserRouter>
        <div> 
            <Route exact path="/" component={Main}/> 
            <Route path="/create_item" component={CreateItem}/>
            <Route path="/item" component={CurrentItem}/>
        </div>
    </BrowserRouter>,
    document.getElementById('app')
);

2) Main.js

import React from 'react';
import { withRouter } from 'react-router-dom';
import { Route, browserHistory } from 'react-router-dom';

export class Main extends React.Component {

    render(){
        const ToCreateItemPageButton = () => (
            <Route render={({ history}) => (
                <button type='button' onClick={() => { history.push('/create_item') }}>Move to create item page!</button>
             )}
            />
        )

        return (
            <div>
                <h1>Main Page</h1>
                <ToCreateItemPageButton/>
            </div>
        );
    }
}

3) CreateItem.js

import React from 'react'; 
import { Route, browserHistory } from 'react-router-dom';

export class CreateItem extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            mainArray: [],
            item: {},
            item_id: 0,
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({item: {item_id: this.state.item_id, 
                       name:event.target.value}});
    }

    handleSubmit(event) {
        if (this.state.item.name.length > 0) {
        this.state.mainArray.push(this.state.item);
        this.state.item_id = this.state.item_id + 1;
        let data = JSON.stringify(this.state.mainArray);
        localStorage.setItem('mainObject', data);
        this.setState(
            {mainArray : this.state.mainArray,
            item_id : this.state.item_id,}
        );
        event.preventDefault();
        }
    }

    render(){
        const ToMainPageButton = () => (
            <Route render={({ history}) => (
                <button type='button' onClick={() => { history.push('/') }}>Move to main page!</button>
             )}
            />
        )
        return (
            <div>
                <h1>Create new item</h1>
                <ToMainPageButton/>
                <form onSubmit={this.handleSubmit}>
                    <label>
                          <input type="text" value={this.state.value} onChange={this.handleChange} />
                    </label>
                <input type="submit" value="Submit" />
                </form>
            </div>

        );
    }
}

Итак, все, что я хочу, это иметь возможность перенести мой mainArray из компонента 'CreateItem' в компонент 'Main' .

1
Stepan Kovalyshyn 2 Янв 2018 в 00:22

2 ответа

Лучший ответ

Вы можете перенаправлять и отправлять такие данные:

this.props.history.push({
  pathname: '/target-path',
  data: [/*your data*/]
});

И получить его на целевом компоненте так:

const { data } = this.props.location;
1
Lefi Tarik 1 Янв 2018 в 21:56

Краткий ответ - Да, это возможно с использованием компонента контейнера, как в fiddle пример.

Таким образом, идея состоит в том, чтобы сохранить массив элементов в состоянии контейнера и передать его «повторяющемуся» компоненту, а также обратному вызову для обработки входящего элемента.

// container component
class Container extends React.Component {
  constructor(props){
    super(props);
    this.state = {
        array: ['Hello', 'Stack', 'Overflow']
    }
    this.handleOnAdd = this.handleOnAdd.bind(this)
  }

  handleOnAdd(item){
    this.setState({
        array: [...this.state.array, item]
    })
  }

  render() {
    return (
      <div>
        // pass shared props to "display" component
        <ChildOneDisplay items={this.state.array} />  
        // pass a callback to CreateItem component
        <ChildTwoAdd onAdd={this.handleOnAdd} />  
      </div>
    );
  }
}

// display component

class ChildTwoAdd extends React.Component{
  constructor(props){
    ...
    this.handleAdd = this.handleAdd.bind(this)
  }
  handleAdd(){
    this.props.onAdd(this.state.item);
    ...
  }
  render(){
    return(
      <div>
        <input
          name="item"
          type="text"
          onChange={this.handleChange}
          value={this.state.item}
        />
        <button onClick={this.handleAdd}>Add Me</button>
      </div>
    )
  }
}

Итак, все, что вам нужно, это обернуть ваши два маршрута компонентом контейнера и передать реквизиты им обоим, как я сделал в этом примере.

// So your container should look like the following one

render(){
  return (
    <div>
       <Route exact path="/" render={() => <Main items={this.state.array}}/> 
       <Route path="/create_item" render={() => <CreateItem onAdd={this.handleAdd}/>}/>
    </div>
  )
}

// And render it as the following
<BrowserRouter>
  <Container />
  <Route path="/item" component={CurrentItem}/>
</BrowserRouter>

Кроме того, я предлагаю взглянуть на redux - это библиотека для управления состоянием вашего приложения.

Благодарность!

1
The Reason 1 Янв 2018 в 22:17