У меня есть несколько компонентов, которые должны делать одно и то же. (Простая функция, которая сопоставляет их дочерние компоненты и что-то делает с каждым из них). На данный момент я определяю этот метод в каждом из компонентов. Но я хочу дать ему определение только один раз.
Я мог бы определить его в компоненте верхнего уровня, а затем передать его как опору. Но это не совсем так. Это больше библиотечная функция, чем опора. (Мне кажется).
Как правильно это сделать?
Ответы:
Если вы используете что-то вроде browserify, тогда у вас может быть внешний файл, например util.js, который экспортирует некоторые служебные функции.
var doSomething = function(num) { return num + 1; } exports.doSomething = doSomething;
Затем потребуйте его по мере необходимости
var doSomething = require('./util.js').doSomething;
источник
Utils.js с новейшим синтаксисом Javascript ES6
Создайте такой
Utils.js
файл с несколькими функциями и т. Д.const someCommonValues = ['common', 'values']; export const doSomethingWithInput = (theInput) => { //Do something with the input return theInput; }; export const justAnAlert = () => { alert('hello'); };
Затем в ваших компонентах, которые вы хотите использовать служебные функции, импортируйте определенные функции, которые необходимы. Вам не нужно импортировать все
import {doSomethingWithInput, justAnAlert} from './path/to/utils.js/file'
А затем используйте эти функции в компоненте следующим образом:
justAnAlert(); <p>{doSomethingWithInput('hello')}</p>
источник
/file
конец строки импорта?Если вы хотите управлять состоянием в вспомогательных функциях, выполните следующие действия:
Создайте файл Helpers.js:
export function myFunc(){ return this.state.name; //define it according to your needs }
Импортируйте вспомогательную функцию в файл вашего компонента:
import {myFunc} from 'path-to/Helpers.js'
В вашем конструкторе добавьте эту вспомогательную функцию к классу
constructor(){ this.myFunc = myFunc.bind(this) }
В вашей функции рендеринга используйте это:
render(){ <div>{this.myFunc()}</div> }
источник
Вот несколько примеров того, как вы можете повторно использовать функцию (
FetchUtil.handleError
) в компоненте React (App
).Решение 1. Использование синтаксиса модуля CommonJS
module.exports = { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, };
Решение 2. Использование createClass (React v16)
util / FetchUtil.js
const createReactClass = require('create-react-class'); const FetchUtil = createReactClass({ statics: { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, }, render() { }, }); export default FetchUtil;
Примечание: если вы используете React v15.4 (или ниже), вам необходимо импортировать
createClass
следующим образом:import React from 'react'; const FetchUtil = React.createClass({});
Источник: https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-reactcreateclass
Компонент (который повторно использует FetchUtil)
компоненты / App.jsx
import Categories from './Categories.jsx'; import FetchUtil from '../utils/FetchUtil'; import Grid from 'material-ui/Grid'; import React from 'react'; class App extends React.Component { constructor(props) { super(props); this.state = {categories: []}; } componentWillMount() { window .fetch('/rest/service/v1/categories') .then(FetchUtil.handleError) .then(response => response.json()) .then(categories => this.setState({...this.state, categories})); } render() { return ( <Grid container={true} spacing={16}> <Grid item={true} xs={12}> <Categories categories={this.state.categories} /> </Grid> </Grid> ); } } export default App;
источник
Другой надежный вариант, кроме создания файла util, - это использование компонента более высокого порядка для создания
withComponentMapper()
оболочки. Этот компонент примет компонент как параметр и вернет его обратно сcomponentMapper()
функцией, переданной как опора.В React это считается хорошей практикой. Подробнее о том, как это сделать, можно узнать здесь.
источник
Звучит как служебная функция, в таком случае почему бы не поместить ее в отдельный статический служебный модуль?
В противном случае, если вы используете транспилятор, такой как Babel, вы можете использовать статические методы es7:
class MyComponent extends React.Component { static someMethod() { ...
Или, если вы используете React.createClass, вы можете использовать объект статики :
var MyComponent = React.createClass({ statics: { customMethod: function(foo) { return foo === 'bar'; } }
Однако я не советую эти варианты, нет смысла включать компонент для служебного метода.
Также вы не должны передавать метод через все ваши компоненты в качестве опоры, это будет тесно связывать их и сделать рефакторинг более болезненным. Советую простой старый служебный модуль.
Другой вариант - использовать миксин для расширения класса, но я не рекомендую этого делать, так как вы не можете этого сделать в es6 + (и я не вижу пользы в этом случае).
источник
React.createClass
не рекомендуется, начиная с React 15.5.0. create-response-app предлагаетcreate-react-class
вместо этого использовать модуль npm .doSomething.js
, или файл с множеством похожих «служебных» функций, например,utils.js
и импортирую те функции, где вам нужно их использоватьНиже я покажу два стиля, и вы захотите выбрать их в зависимости от того, насколько логика компонентов связана друг с другом.
Стиль 1 - Относительно связанные компоненты могут быть созданы с помощью ссылок обратного вызова, например, в
./components/App.js
...<SomeItem ref={(instance) => {this.childA = instance}} /> <SomeOtherItem ref={(instance) => {this.childB = instance}} />
И тогда вы можете использовать общие функции между ними вот так ...
this.childA.investigateComponent(this.childB); // call childA function with childB as arg this.childB.makeNotesOnComponent(this.childA); // call childB function with childA as arg
Стиль 2 - компоненты служебного типа могут быть созданы таким образом в
./utils/time.js
...export const getTimeDifference = function (start, end) { // return difference between start and end }
А потом их можно использовать вот так, в
./components/App.js
...import React from 'react'; import {getTimeDifference} from './utils/time.js'; export default class App extends React.Component { someFunction() { console.log(getTimeDifference("19:00:00", "20:00:00")); } }
Что использовать?
Если логика относительно взаимосвязана (они используются вместе только в одном приложении), тогда вы должны разделять состояния между компонентами. Но если ваша логика имеет отдаленное отношение (например, утилита для математики, утилита для форматирования текста), тогда вам следует создать и импортировать функции класса util.
источник
Разве для этого не стоит использовать миксин? См. Https://facebook.github.io/react/docs/reusable-components.html.
Хотя они и впадают в немилость, см. Https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750.
Может быть полезно
источник