@Lifehack043

Как передать данные из модели в компонент React(гем React-rails)?

Приветствую всех! Предложите совет, как объявить данные в компоненте, кроме того что переключить контроллер на режим апи?

===============================================================================

app/views/users/index.html.haml
#root
= javascript_pack_tag 'SearchUsers', {data: @users.to_json(only: [:id, :name, :email]) }

===============================================================================
/app/javascript/packs/SearchUsers.jsx
import React, {Component} from 'react';
import PropTypes from "prop-types";
import ReactDOM from 'react-dom';

var data = this.props.data 

const User = ({name, email}) =>
<section id={name}> 
 <h1> {name} </h1>
  <h2> {email} </h2>
  </section>

const Users = ({user})=>
  <div className="users">
  {user.map((user, i) => 
    <User key={i} {...user} />
    )}
    </div>
  
  
ReactDOM.render(
  <Users user={data} />,
  document.getElementById('root')
);

контроллер:
def index
@users = User.where(activated: true)
end

===============================================================================
и ошибка:
Uncaught TypeError: Cannot read property 'data' of undefined
  • Вопрос задан
  • 393 просмотра
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Ошибка тут:
var data = this.props.data
this.props - это свойства компонента и вызывать их можно только внутри class component - компонента созданного через расширение класса React.Component:
class Example extends React.Component {
  render() {
    return <span>{this.props.someValue}</span>;
  }
}


В functional component props являются аргументом:
function Example (props) {
  return <span>props.someValue</span>;
}


Вы же пытаетесь получить props из контекста глобального скоупа, который является undefined.

Смотрите, вы пишите данные в атрибут data тега script:
#root
= javascript_pack_tag 'SearchUsers', {data: @users.to_json(only: [:id, :name, :email]) }

Записываются они в виде JSON строки и их необходимо распарсить.
Это делается так:
import React, {Component} from 'react';
import PropTypes from "prop-types";
import ReactDOM from 'react-dom';

let data = [];  // задаем значение по-умолчанию

try {
  data = JSON.parse(document.querySelector('script[data]').getAttribute('data'));  
} catch(e) {
  console.log(e);  // тут можно обработать ошибку парсинга данных
}

const User = ({ name, email }) => (
  <section id={name}> 
    <h1> {name} </h1>
    <h2> {email} </h2>
  </section>
);

const Users = ({ user }) => (
  <div className="users">
    {user.map(user => 
      <User key={user.id} {...user} />  // обратите внимание, заменено значение свойства key
    )}
  </div>
);
  
ReactDOM.render(
  <Users user={data} />,
  document.getElementById('root')
);


Блок try catch нужен, чтобы обработать исключение SyntaxError, если данные по какой-то причине будут записаны в тег с ошибкой. В этом случае приложение получит дефолнтное значение, которое мы присвоили при инициализации. В данном примере это пустой массив.

Демо с простым примером без react: https://jsfiddle.net/e9q5x2ne/

Для списка пользователей используйте для свойства key используйте user.id, вместо i.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
29 нояб. 2024, в 10:38
5000 руб./за проект
29 нояб. 2024, в 10:27
100000 руб./за проект
29 нояб. 2024, в 09:43
100000 руб./за проект